I have an aysnc function which loop thru an array, make another aync call for each element, wait for result.
public async myfetch(parent_id: string): Promise<Record[]> {
let payload = await this.load(parent_id);
let records = [];
await payload.items.forEach(async (item: any) => {
let child = await this.load_another_api(item.child_id);
let record = {
a: child.a,
b: child.b,
}
records.push(record)
}
return records;
}
And signtgure of load, load_another_api are like:
public async load(Id: string): Promise<any> {
/// some logic to build requestUrl
return fetch(requestUrl, options)
.then((response) => { return response.json(); });
}
But when I debug, I see that myfetch function returns to the caller before all the for loop items have been called load_another_api
and wait for the result and populate to records
array.
Can you please tell me what am I missing?
CodePudding user response:
You can't make an asynchronous forEach
loop. But, you have two workarounds here:
- Use a
for
loop instead:
public async myfetch(parent_id: string): Promise<Record[]> {
let payload = await this.load(parent_id);
let records = [];
for (let index: number = 0; index < payload.items.length; index ) {
const item: any = payload.items[index];
let child = await this.load_another_api(item.child_id);
let record = {
a: child.a,
b: child.b
};
records.push(record);
}
return records;
}
- Wait for the
forEach
to finish with aPromise
public async myfetch(parent_id: string): Promise<Record[]> {
let payload = await this.load(parent_id);
let records = [];
await new Promise<void>((resolve) => {
payload.items.forEach(async (item: any, index: number) => {
let child = await load_another_api(item.child_id);
let record = {
a: child.a,
b: child.b
};
records.push(record);
// Condition to resolve promise
if (index == payload.items.length - 1) {
resolve();
}
});
});
return records;
}
CodePudding user response:
You can do this using array.prototype.map and Promise.all instead. Something like this:
public async myfetch(parent_id: string): Promise<Record[]> {
const payload = await this.load(parent_id);
const promises = payload.items.map((item: any) =>
this.load_another_api(item.child_id)
.then((child: any) => ({a: child.a, b: child.b})));
return Promise.all(promises);
}