Reputation: 14129
I have the following code:
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");
When it's run, the console reads:
TEST 1
TEST 2
TEST 4
getReservations()
TEST 3
But I want it to wait for getReservations()
to finish before it continues past the forEach()
. I would like it to output:
TEST 1
TEST 2
getReservations()
TEST 3
TEST 4
Any ideas?
Upvotes: 0
Views: 154
Reputation:
To expand on the other answers, if you really want to use forEach
, you could write your own version of it, which we will call 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"));
Upvotes: 1
Reputation: 1561
I don't believe you can, however, the code below would work.
(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");
})();
Upvotes: 1
Reputation: 1
This is one time a regular for
loop works better - the code below is wrapped in an IIFE so await
can be used
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
})();
NOTE: anything AFTER the IIFE will not "await"
Upvotes: 2
Reputation: 33141
If you are happy running all your getReservations functions at the same time, you can use Promise.all()
. For example:
Promise.all(accounts.map(getReservations))
.then(() => console.log('all get reservations completed'))
Or, if you need each call to getReservations
to be completed in order, you can build a promise chain using reduce()
. For example:
accounts.reduce((p, account) => {
return p.then(() => getReservations(account)
}, Promise.resolve())
.then(() => console.log('all get reservations completed'))
Upvotes: 1