【问题标题】:Order of execution of several then() linked to a single promise几个 then() 的执行顺序链接到一个单一的承诺
【发布时间】:2017-06-24 02:05:38
【问题描述】:

我有一个处理 Chrome 窗口事件的事件处理程序。为了处理这些事件,我在 promise 中调用 async chrome.windows.get 并使用 then() 来处理事件。

问题是当多个then() 链接到单个promise 解决时,它们的执行顺序与源事件顺序不同。例如,我收到事件 1,2 和 3,但执行顺序可能是 3、2、1。

我需要所有then() 都按照事件发生的顺序执行。

简化代码示例:

chromeWinRequests = new Map();

function eventHandler(windowId) {
  if (!chromeWinRequests.has(windowId)) {
    chromeWinRequests.set(windowId, new Promise((resolve, reject) => {
       chrome.windows.get(windowId, {populate: true}, (cwin) => {
         if (!chrome.runtime.lastError) {
           resolve(cwin);
         } else {
           reject(chrome.runtime.lastError.message);
         }
       });
    }));
  }

  chromeWinRequests.get(windowId).then((cwin) => {
     // process event here
     // when I get here, the source order of events is not preserved
  });
}

我可以做些什么来保留处理顺序吗?

提前谢谢你。

【问题讨论】:

  • 当你说你得到事件 1、2 和 3 时,你的代码在哪里?我在任何地方都没有看到,因此不明白这个问题。
  • 答案不属于问题。

标签: javascript promise


【解决方案1】:

代替:

chromeWinRequests.get(windowId).then((cwin) => {
    // process event here
    // when I get here, the source order of events is not preserved
});

使用Promise.all,这将确保在进入then 回调之前所有之前收集的promise 都已解决。在那里,您需要获得在此上下文中创建的承诺的价值:

Promise.all(
    Array.from(chromeWinRequests, ([windowId, promise]) => promise)
).then( (cwins) => {
    const cwin = cwins.pop(); // get the promised value we're interested in
    console.log(cwin);
    // further processing....
});

【讨论】:

  • 我不得不链接承诺,而不是将多个 then() 链接到单个承诺。答案已经公布。谢谢。
  • 这比链接更有效。在您给自己的答案中,您没有在地图中一个接一个地链接承诺。
  • 1.关于你的例子。我没有太多需要等待的承诺,我只有一个承诺,我希望在解决所有事件后处理所有事件。在您的示例中,它正在等待所有窗口的所有承诺 - 这不是我想要的。 2. 在我发布的解决方案中,我将第一个承诺替换为 then() 承诺,该承诺将在事件处理后解决。所以下一个事件将不会链接到 get() 承诺,而是链接到上一个事件的 then() 承诺。确实,它有效,我已经检查过了。
  • 如果你有“一个单一的承诺”,你怎么能被束缚?您的函数和地图建议您要在地图中存储多个承诺,我从您的问题中了解到,您希望相应的 then 回调(复数)以与您在地图中存储承诺相同的顺序执行。请注意,我的代码不会等待所有承诺解决:只有那些之前的承诺,这正是您想要的,因为否则then 回调将按顺序执行。无论如何,如果您认为它已解决,我可以。但对我来说,你的问题和答案不匹配
【解决方案2】:

通过将最后一段代码更改为以下代码解决了问题:

newPromise = chromeWinRequests.get(windowId).then((cwin) => {
     // process event here
     return cwin;
});
chromeWinRequests.set(windowId, newPromise);

感谢Luizgrs

【讨论】:

  • 这没什么意义,因为没有使用新承诺的代码,所以它等同于你已经拥有的。
  • 新的即将到来的事件使用新的承诺,因此它们链接成一个链。
  • 这就是你所说的,但它不在你的解决方案中。您在这里写的只是在您存储在地图中的承诺中再添加一个then,仅此而已。所以这不会改变任何事情。如果您有解决方案,则不是这部分代码可以解决问题。
猜你喜欢
  • 2018-03-18
  • 2019-09-08
  • 2020-06-16
  • 2020-01-06
  • 2013-11-25
  • 2016-12-30
  • 2019-02-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多