次のコードがあるとします。
var arr = [1,2,3,4,5];
var results: number[] = await arr.map(async (item): Promise<number> => {
await callAsynchronousOperation(item);
return item + 1;
});
次のエラーが発生します。
TS2322:タイプ 'Promise <number> []'はタイプ 'number []'に割り当て可能ではありません。タイプ '約束' <番号>はタイプ '番号'に割り当て可能ではありません。
どうすれば修正できますか? async await
とArray.map
を連携させるにはどうすればよいですか?
ここでの問題は、あなたが約束ではなく約束の配列をawait
しようとしていることです。これはあなたが期待することをしません。
await
に渡されたオブジェクトがPromiseではない場合、await
は解決しようとするのではなく、ただちにその値をそのまま返します。そのため、ここではPromiseの代わりにawait
に(Promiseオブジェクトの)配列を渡したので、awaitによって返される値は単にPromise<number>[]
型のその配列になります。
ここでする必要があるのは、map
を返す前に、それを単一のPromiseに変換するために、await
によって返される配列に対してPromise.all
を呼び出すことです。
Promise.all
のMDNドキュメントによると、
Promise.all(iterable)
メソッドは、iterable引数内のすべてのpromiseが解決された場合に解決するpromiseを返すか、最初に渡されたpromiseが拒否されたことを理由にrejectします。
だからあなたの場合:
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;
}));
これはあなたがここで遭遇している特定のエラーを解決するでしょう。
ネイティブのPromiseではなくBluebirdを使用している場合は、それに対する別の解決策があります。
Promise.map() を使用して、array.mapとPromise.allを混在させることもできます。
あなたの場合:
var arr = [1,2,3,4,5];
var results: number[] = await Promise.map(arr, async (item): Promise<number> => {
await callAsynchronousOperation(item);
return item + 1;
});
あなたが約束の配列にマップするなら、あなたはそれから数の配列にそれらすべてを解決することができます。 Promise.all を参照してください。
上記のようにPromise.allを使用することをお勧めしますが、そのアプローチを避けたい場合は、forまたは他のループを実行できます。
const arr = [1,2,3,4,5];
let resultingArr = [];
for (let i in arr){
await callAsynchronousOperation(i);
resultingArr.Push(i + 1)
}