【问题标题】:How to dynamically stack Promises sequentially如何按顺序动态堆叠 Promise
【发布时间】:2019-07-10 22:30:52
【问题描述】:

我正在编写一个电子应用程序。在渲染器进程中,有一个事件的处理。

事件可以以可能重叠的方式多次触发。所以需要堆叠和顺序处理事件实例,如果它们重叠的话。

ipcRenderer.on('doWork', function (event, args) {
   doWork();
});

由于目标是防止 doWork 执行重叠,因此已尝试以执行的方式使其成为 Promise,如果有更多事件发生,它们就会堆积起来。但我无法构建算法。

我在 stackoverflow 上发现的其他问题总是关于预定义/已知数量的 Promise(如果我遗漏了什么,请见谅)。

编辑:问题如下:

How can I execute array of promises in sequential order?

Execute many promises sequentially (Concept)

doWork 内部,我正在调用电子的desktopCapturer.getSources,它是异步的。然后我保存到文件系统,并确保保存最大数量的屏幕截图,但这些使用的是同步 Nodejs 操作。

【问题讨论】:

  • 是否可以包含指向“其他”堆栈溢出问题的链接?
  • doWork 执行永远不会重叠,除非它本身调用异步 API。但除非这是真的,否则它将使 JS 保持忙碌,并且在 doWork 完成之前不会处理任何新事件。因此,您可以看到提供有关 doWork 的详细信息很重要。
  • 堆栈承诺正是您想要避免的。考虑改用 Observables
  • 搜索词queuing promises
  • @MaximeLaunois 是的,您可以将该问题标记为可能与另一个问题重复

标签: javascript promise electron


【解决方案1】:

假设您成功地使 doWork() 返回了一个 Promise,您可以链接每个调用返回的 Promise:

let promise = Promise.resolve();
ipcRenderer.on('doWork', function (event, ...args) {
   promise = promise.then(doWork);
});

如果参数必须传递给doWork

let promise = Promise.resolve();
ipcRenderer.on('doWork', function (event, ...args) {
   promise = promise.then(() => doWork(...args));
});

但请注意,如果事件发生率高于doWork 可以处理的速度,您的链会变得越来越长。如果真的必须进行所有这些调用,那么这并不是一个真正的问题。

但在某些情况下,跳过调用并只执行“最后一个”调用可能是可以接受且更有趣的。如果这是一个选项,那么请查看许多“去抖动”实现中的一个。或者,当有更新的请求进来时,这里有一个跳过调用的想法:

let promise = Promise.resolve();
let pendingArgs = null;
ipcRenderer.on('doWork', function (event, ...args) {
    const isPending = pendingArgs !== null;
    pendingArgs = args; // doWork should be called with the latest version of args
    if (isPending) return; // There is already a pending request to doWork
    promise = promise.then(() => {
        const args = pendingArgs;
        pendingArgs = null;
        return doWork(...args);
    });
});

【讨论】:

  • 谢谢,但在这种情况下,在第一次出现 doWork 之后,promise 将被解决,第二次出现不会被执行。也许我应该尝试在其他地方同步。
  • 当然,第二个会被执行,主要是因为这个promise已经确定了。这就是为什么我们甚至以一个确定的承诺开始。请注意,每个then 调用都会创建一个分配给promise 变量的new 承诺,因此您会获得许多结算。你试过了吗?
  • 是的,我做到了,仍在尝试看看我是否在这里遗漏了什么,再次感谢。
  • 我的第一条评论的意思是,第二个传入事件在之前的 Promise 被解决(由第一个事件处理产生)之后到达。猜猜这就是为什么第二个没有处理的原因。相信我最好退后一步重新检查我的设计。
  • 但是当一个promise被解决时,then回调保证在它上面执行(如果promise之前解决了long),所以doWork 将被调用。我不明白你是如何推断它不会被调用的。我测试了这段代码,它的行为符合我的预期。如果你有一个可以显示你所得到的东西的小提琴,我会很高兴看看它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多