Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use async await with Array.map

Given the following code:

var arr = [1,2,3,4,5];  var results: number[] = await arr.map(async (item): Promise<number> => {         await callAsynchronousOperation(item);         return item + 1;     }); 

which produces the following error:

TS2322: Type 'Promise<number>[]' is not assignable to type 'number[]'. Type 'Promise<number> is not assignable to type 'number'.

How can I fix it? How can I make async await and Array.map work together?

like image 684
Alon Avatar asked Oct 19 '16 19:10

Alon


People also ask

How do you use async await in array map?

So, the solution is to use Promise. all() function in javascript. We need to wrap the array inside the Promise. all(array) function which will then wait for all the promises to get resolved and return the result to the user.

Is array map async?

The . map() algorithm applies an async callback to each element of an array, creating promises as it does. However, the returned result by . map() is no promise, but an array of promises.

Can we use async in map function?

You would have to implement either callbacks or promises in the function you are using inside map. Probably a good introduction in using of async functions inside Array. map was suggested by Tamás Sallai. As a result use Promise.


1 Answers

The problem here is that you are trying to await an array of promises rather than a Promise. This doesn't do what you expect.

When the object passed to await is not a Promise, await simply returns the value as-is immediately instead of trying to resolve it. So since you passed await an array (of Promise objects) here instead of a Promise, the value returned by await is simply that array, which is of type Promise<number>[].

What you probably want to do is call Promise.all on the array returned by map in order to convert it to a single Promise before awaiting it.

According to the MDN docs for Promise.all:

The Promise.all(iterable) method returns a promise that resolves when all of the promises in the iterable argument have resolved, or rejects with the reason of the first passed promise that rejects.

So in your case:

var arr = [1, 2, 3, 4, 5];  var results: number[] = await Promise.all(arr.map(async (item): Promise<number> => {     await callAsynchronousOperation(item);     return item + 1; })); 

This will resolve the specific error you are encountering here.

Depending on exactly what it is you're trying to do you may also consider using Promise.allSettled, Promise.any, or Promise.race instead of Promise.all, though in most situations (almost certainly including this one) Promise.all will be the one you want.

like image 132
Ajedi32 Avatar answered Sep 25 '22 10:09

Ajedi32