Reputation: 3498
I have a bit of code with await
-s set like this:
async calculateDeletionResidualsData(res) {
//console.log("resss is:");
//console.log(res);
let selectedCountries = this.countriesList.filter(c => c.selected);
let selectedIndicators = this.indicatorsList.filter(i => i.selected);
await selectedCountries.forEach(async c => {
// taking each (selected) country
await selectedIndicators.forEach(async i => {
// taking each (selected) indicator
// Form the series for the calculation of residuals
let series = [];
deletionResidualsRelevantYears.forEach(y => {
series.push(res[c.label][y][i.label][0]);
});
// Calculate deletion residuals
let drr = await util.calculateDeletionResidualsStatistics(
deletionResidualsRelevantYears.length,
series,
this.deletionResidualsService
);
this.drr[c.label][i.label] = drr;
});
});
console.log("setting qrReady to true");
this.qrReady = true;
}
I can clearly see that the calls to the util.calculateDeletionResidualsStatistics
are still being made in the network tab of my browser, but I also see that the console.log("setting qrReady to true");
has already been fired, and it shouldn't be fired. Why are all these awaits skipped and jumped over to the last line of code?
Upvotes: 2
Views: 1216
Reputation: 54741
You need to use Promise.all() with await
if you have a collection of promises, and use a map()
operation to create an array of promises.
await Promise.all(selectedCountries.map(async c => {
await Promise.all(selectedIndicators.map(async i => {
let drr = await util.calculateDeletionResidualsStatistics(...);
// ...
});
});
console.log('printed after everything is finished');
Keep in mind that Promise.all()
will resolve an array of results after all of the inner promises have resolved. The order of those promises is unpredictable as they resolve in parallel.
You will end up with nested Promise.all()
that will resolve in batches before the top level Promise.all()
resolves.
Since it looks like you are discarding the results of the outer promises, then I don't see a real issue here with the order. You just want to run some code after everything is done.
Upvotes: 1
Reputation: 2250
await
only works on functions that return a Promise
. forEach
does not. Assuming util.calculateDeletionResidualsStatistics
returns a Promise
, write your code like this instead:
calculateDeletionResidualsData(res) {
//console.log("resss is:");
//console.log(res);
let selectedCountries = this.countriesList.filter(c => c.selected);
let selectedIndicators = this.indicatorsList.filter(i => i.selected);
selectedCountries.forEach( c => {
// taking each (selected) country
selectedIndicators.forEach(async i => {
// taking each (selected) indicator
// Form the series for the calculation of residuals
let series = [];
deletionResidualsRelevantYears.forEach(y => {
series.push(res[c.label][y][i.label][0]);
});
// Calculate deletion residuals
let drr = await util.calculateDeletionResidualsStatistics(
deletionResidualsRelevantYears.length,
series,
this.deletionResidualsService
);
this.drr[c.label][i.label] = drr;
});
});
console.log("setting qrReady to true");
this.qrReady = true;
}
If not, please edit your post and I'll try to provide a different solution.
Upvotes: 1
Reputation: 2587
await
won't work for loops that use callbacks. Don’t ever use await with forEach. Use a for-loop (or any loop without a callback) instead
forEach
is not promise-aware. It cannot support async and await. You cannot use await in forEach.
Upvotes: 4