Gegeben den folgenden Code:
var arr = [1,2,3,4,5];
var results: number[] = await arr.map(async (item): Promise<number> => {
await callAsynchronousOperation(item);
return item + 1;
});
Dies führt zu folgendem Fehler:
TS2322: Der Typ 'Versprechen <Nummer> []' kann nicht dem Typ 'Nummer []' zugewiesen werden. Der Typ 'Versprechen <Nummer> kann nicht dem Typ' Nummer 'zugewiesen werden.
Wie kann ich es reparieren? Wie kann ich machen async await
und Array.map
zusammen arbeiten?
arr.map()
ist synchron und gibt kein Versprechen zurück.map
, die eine synchrone erwartet und erwartet, dass sie funktioniert.async
, diese Funktion ein Versprechen zurückgibt. Natürlich gibt eine Karte von Async eine Reihe von Versprechungen zurück :)Antworten:
Das Problem hierbei ist, dass Sie
await
eher eine Reihe von Versprechungen als ein Versprechen versuchen . Dies macht nicht das, was Sie erwarten.Wenn das übergebene Objekt
await
kein Versprechen ist, wirdawait
der Wert sofort unverändert zurückgegeben, anstatt zu versuchen, ihn aufzulösen. Da Sieawait
hier also anstelle eines Versprechens ein Array (von Promise-Objekten) übergeben haben, ist der von await zurückgegebene Wert einfach das Array vom TypPromise<number>[]
.Was Sie hier tun müssen, ist
Promise.all
das von zurückgegebene Array aufzurufenmap
, um es in ein einzelnes Versprechen umzuwandeln, bevorawait
Sie es ausführen .Gemäß den MDN-Dokumenten für
Promise.all
:Also in deinem Fall:
Dadurch wird der spezifische Fehler behoben, auf den Sie hier stoßen.
quelle
:
Doppelpunkte?callAsynchronousOperation(item);
mit und ohneawait
innerhalb der asynchronen Kartenfunktion?await
wartet die Funktion jedoch, bis der asynchrone Vorgang abgeschlossen ist (oder fehlschlägt), bevor sie fortgesetzt wird. Andernfalls wird sie sofort fortgesetzt, ohne zu warten.Es gibt eine andere Lösung dafür, wenn Sie keine nativen Versprechen verwenden, sondern Bluebird.
Sie können auch versuchen, Promise.map () zu verwenden , indem Sie array.map und Promise.all mischen
In Ihrem Fall:
quelle
Promise.mapSeries
oderPromise.each
sind sequenziell,Promise.map
startet sie alle auf einmal.concurrency
Option angeben .Wenn Sie einem Array von Versprechungen zuordnen, können Sie sie alle in ein Array von Zahlen auflösen. Siehe Promise.all .
quelle
Ich würde empfehlen, Promise.all wie oben erwähnt zu verwenden, aber wenn Sie diesen Ansatz wirklich vermeiden möchten, können Sie eine for- oder eine andere Schleife ausführen:
quelle
Lösung unten, um alle Elemente eines Arrays asynchron zu verarbeiten UND die Reihenfolge beizubehalten:
Auch Codepen .
Beachten Sie, dass wir nur auf Promise.all "warten". Wir rufen calc an, ohne mehrmals zu warten, und sammeln sofort eine Reihe ungelöster Versprechen. Dann wartet Promise.all auf die Auflösung aller und gibt ein Array mit den aufgelösten Werten in der angegebenen Reihenfolge zurück.
quelle