0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

非同期的に配列をforEachする方法

Posted at

やってはだめ、想像する非同期的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(すべてを待つ)ということです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?