やってはだめ、想像する非同期的forEach
これは絶対にしないでください。asyncを付けた関数内で非同期処理がなかった場合同期的に実行されますが、もし非同期処理があった場合はmicroqueue stackにプッシュされ、次のイベントループまでそれらが実行されることは無くなってしまいます
JavaScript版
async function getImportsProps(list){
let props = [];
list.forEach(async e=>
props.push(...Object.keys(await import(e))));
return props;
}
TypeScript版
async function getImportsProps(list: string[]): Promise<string[]>{
let props: string[] = [];
list.forEach(async e=>
props.push(...Object.keys(await import(e))));
return props;
}
これぞ正義、正しい非同期的forEach
JavaScript版
async function getImportsProps(list){
let props = [];
await Promise.all(list.map(async e=>
props.push(...Object.keys(await import(e)))));
return props;
}
TypeScript版
async function getImportsProps(list: string[]): Promise<string[]>{
let props: string[] = [];
await Promise.all(list.map(async e=>
props.push(...Object.keys(await import(e)))));
return props;
}
解説
まずasync関数の返り値は、宣言したものではなくそのPromise型なのです。
つまりはasyncのついた関数はPromiseを返す。
それをlist.map
したわけですが、つまりこれはPromise[]
を返すのです。
次にPromise.all
。これはPromise[]
を渡すとそれが全部完了するまでの非同期処理のPromiseを返します。
それをawaitした場合、全部を待つということです。
自分はうまく解説できません。すみません。
つまりPromise(async関数) > Promise[](forEachのPromiseリスト) > Promise(全部完了したら完了する) > await(すべてを待つ)
ということです。