2

我有一个看起来像这样的循环:

    newThreadIds.map(async function(id) {
      let thread = await API.getThread(id);
      await ActiveThread.findOneAndUpdate({number: id}, {posts: thread.posts}, {upsert: true}).exec();
      await Q.delay(1000);
    });

问题是每次迭代都是异步执行的,我希望它们之间有 1 秒的延迟。我知道如何使用 Promise 来做到这一点,但它看起来很难看,我更愿意使用 async/await 和尽可能少的嵌套来做到这一点。

4

2 回答 2

7

map函数不知道它的回调是异步的并返回一个承诺。它只是立即遍历数组并创建一个 Promise 数组。你会像这样使用它

const promises = newThreadIds.map(async function(id) {
    const thread = await API.getThread(id);
    return ActiveThread.findOneAndUpdate({number: id}, {posts: thread.posts}, {upsert: true}).exec();
});
const results = await Promise.all(promises);
await Q.delay(1000);

对于顺序执行,您需要使用Bluebird 的mapSeries函数(或您各自库中的类似函数),它关心每次迭代的承诺返回值。

在纯 ES6 中,您必须使用一个实际的循环,其控制流将尊重await循环体中的关键字:

let results = [];
for (const id of newThreadIds) {
    const thread = await API.getThread(id);
    results.push(await ActiveThread.findOneAndUpdate({number: id}, {posts: thread.posts}, {upsert: true}).exec());
    await Q.delay(1000);
}
于 2016-02-25T16:30:03.603 回答
6

我想通了:

    for (let id of newThreadIds) {
      let thread = await API.getThread(id);
      await ActiveThread.findOneAndUpdate({number: id}, {posts: thread.posts}, {upsert: true}).exec();
      await Q.delay(1000);
    }

这可能是使用 ES2015 和 async/await 的最佳方式。

于 2016-02-25T16:14:28.880 回答