如何使async / await以异步方式同步进行forEach()同步?

时间:2017-04-21 04:16:05

标签: javascript promise

我有以下代码:

console.log("TEST 1");
accounts.forEach(async function(account) {
    console.log("TEST 2");
    try {
        var data = await getReservations(account);
    } catch(err) {
        res.status(err.error_code).json(err);
    }
    console.log("TEST 3");
});
console.log("TEST 4");

当它运行时,控制台显示:

TEST 1
TEST 2
TEST 4
getReservations()
TEST 3

但我希望它等待getReservations()完成,然后再继续forEach()。我想输出:

TEST 1
TEST 2
getReservations()
TEST 3
TEST 4

有什么想法吗?

4 个答案:

答案 0 :(得分:2)

这是常规for循环效果更好的一次 - 下面的代码包含在IIFE中,因此await可以使用



var accounts = [1, 3];
var getReservations = (account) => new Promise(resolve => setTimeout(resolve, 1000, account*2));
(async function() {
    console.log("TEST 1");
    for(var i = 0, l = accounts.length; i < l; i++) {
        let account = accounts[i];
        console.log("TEST 2");
        try {
            var data = await getReservations(account);
        } catch(err) {
            console.error(err);
        }
        console.log("TEST 3");
    };
    console.log("TEST 4", data); // data should be 6
})();
&#13;
&#13;
&#13;

  

注意:IIFE之后的任何事情都不会等待&#34;

答案 1 :(得分:1)

如果您乐意同时运行所有getReservations函数,则可以使用Promise.all()。例如:

Promise.all(accounts.map(getReservations))
  .then(() => console.log('all get reservations completed'))

或者,如果您需要按顺序完成对getReservations的每次调用,您可以使用reduce()建立一个承诺链。例如:

accounts.reduce((p, account) => {
  return p.then(() => getReservations(account)
}, Promise.resolve())
  .then(() => console.log('all get reservations completed'))

答案 2 :(得分:1)

我不相信你可以,但是,下面的代码可行。

(async function()
{   
    console.log("TEST 1");

    for (let i = 0; i < accounts.length; ++i)
    {
        let account = accounts[i];

        console.log("TEST 2");

        try
        {
            var data = await getReservations(account);
        }
        catch (err)
        {
            res.status(err.error_code).json(err);
        }

        console.log("TEST 3");
    }

    console.log("TEST 4");
})();

答案 3 :(得分:1)

要扩展其他答案,如果您真的想使用forEach,可以编写自己的版本,我们会调用forEachAsync

async function forEachAsync(array, fn, thisArg) {
  for (let i = 0; i < array.length; i++) 
    await fn.call(thisArg, array[i], i, array);
}

// Fake version of getReservations--just wait for a while.
function getReservations(account) {
  return new Promise(resolve => setTimeout(() => resolve(account), account));
}

const accounts = [1000, 500, 2000];  

console.log("TEST 1");
forEachAsync(accounts, async function(account) {
    console.log("TEST 2");
    var data = await getReservations(account);
    console.log("TEST 3", data);
})
.then(() => console.log("TEST 4"));