Biorąc pod uwagę następujący kod:
var arr = [1,2,3,4,5];
var results: number[] = await arr.map(async (item): Promise<number> => {
await callAsynchronousOperation(item);
return item + 1;
});
co powoduje następujący błąd:
TS2322: Typu „Promise <numer> []” nie można przypisać do typu „numer []”. Typu „Promise <number> nie można przypisać do typu„ number ”.
Jak mogę to naprawić? Jak mogę tworzyć async await
i Array.map
współpracować?
arr.map()
jest synchroniczny i nie zwraca obietnicy.map
, która oczekuje operacji synchronicznej i oczekuje, że zadziała.async
, sprawiasz, że funkcja zwraca obietnicę. Więc oczywiście mapa asynchronii zwraca tablicę obietnic :)Odpowiedzi:
Problem polega na tym, że próbujesz
await
wypełnić szereg obietnic, a nie obietnicę. To nie robi tego, czego oczekujesz.Gdy obiekt przekazany do
await
nie jest obietnicą,await
po prostu zwraca wartość bez zmian, zamiast próbować ją rozwiązać. Więc ponieważ przekazałeś tutajawait
tablicę (obiektów Promise) zamiast Promise, wartość zwracana przez await jest po prostu tablicą, która jest typuPromise<number>[]
.To, co musisz tutaj zrobić, to wywołanie
Promise.all
tablicy zwróconej przezmap
w celu przekonwertowania jej na pojedynczą obietnicę przedawait
jej rozpoczęciem .Według dokumentów MDN dla
Promise.all
:Więc w twoim przypadku:
To rozwiąże konkretny błąd, który napotkasz tutaj.
źródło
:
oznaczają dwukropki?callAsynchronousOperation(item);
zawait
funkcją mapy asynchronicznej i bez niej?await
funkcja będzie czekać na zakończenie (lub niepowodzenie) operacji asynchronicznej przed kontynuowaniem, w przeciwnym razie będzie kontynuowana natychmiast bez czekania.Jest na to inne rozwiązanie, jeśli nie używasz natywnych obietnic, ale Bluebird.
Możesz także spróbować użyć Promise.map () , mieszając array.map i Promise.all
W twoim przypadku:
źródło
Promise.mapSeries
lubPromise.each
są sekwencyjne,Promise.map
uruchamia je wszystkie naraz.concurrency
opcję.Jeśli odwzorujesz na tablicę obietnic, możesz następnie przekształcić je wszystkie w tablicę liczb. Zobacz Promise.all .
źródło
Zalecałbym użycie Promise.all, jak wspomniano powyżej, ale jeśli naprawdę chcesz uniknąć tego podejścia, możesz wykonać pętlę for lub inną:
źródło
Rozwiązanie poniżej, aby asynchronicznie przetwarzać wszystkie elementy tablicy ORAZ zachować kolejność:
Również codepen .
Zauważ, że „czekamy” tylko na Promise.all. Wielokrotnie dzwonimy do calc bez „czekania” i od razu zbieramy szereg nierozwiązanych obietnic. Następnie Promise.all czeka na rozwiązanie wszystkich z nich i zwraca w kolejności tablicę z rozwiązanymi wartościami.
źródło