JavaScriptでループの中で非同期処理を書く

JavaScriptでループの中で非同期処理を書く:

for文やmap関数の中でasync/awaitを使うときの書き方をメモします。

各非同期処理を逐次的に実行する方法と、非同期的に実行する方法の2つがあります。


1. 同期的に実行



キャプチャ2.gif



2. 非同期的に実行



キャプチャ2.gif


awaitを使いたい非同期処理は以下

sleep.js
// 引数に指定した秒数だけ待つsleep関数 
// Promiseを返す 
function sleep(second) { 
    return new Promise(resolve => { 
        setTimeout(() => { 
            resolve() 
        }, second * 1000) 
    }) 
} 


1. 同期的に実行する方法

for文の中でawaitを使って書くと、forループの中身を順番に処理してくれるので、同期的に実行してくれます。ここではカウンタを使ったfor文を書いていますが、for .. of文を使っても同じ挙動になります。

syncLoop.js
async function syncLoop() { 
    // 1~5までのランダムな整数の配列を生成 
    const ram_arr = Array(5).fill(0).map(() => Math.floor(Math.random() * 5 + 1)) 
 
    // for文を使ってループ処理する 
    for (let i = 0; i < ram_arr.length; i++) { 
        await sleep(ram_arr[i]) // n秒待つ 
        console.log(i+1 + "番目の処理が完了!!" + "待ち時間は" + ram_arr[i] + "秒!!") 
    } 
    console.log("終了!!") 
} 
 
// 実行 
// awaitはトップレベルで使うことができない(ES2017時点)ので 
// asyncをつけた即時関数を作って呼び出している 
(async ()=>{ 
    console.log("同期的に呼び出す") 
    await syncLoop() 
}).call() 


2. 非同期的に実行する方法

mapを使います。mapの引数に指定する関数をasync関数にしておくことで、mapの中で呼ばれる処理を非同期に実行しつつ、mapの返り値であるPromise<void>[]Promise.all()関数で待ち受けることで、 すべての処理の完了を待つことができます。

asyncLoop.js
async function asyncLoop() { 
    // 1~5までのランダムな整数の配列を生成 
    const ram_arr = Array(5).fill(0).map(() => Math.floor(Math.random() * 5 + 1)) 
 
    // mapを使ってループ処理する 
    await Promise.all(ram_arr.map(async (n, i) => { 
        await sleep(n) // n秒待つ 
        console.log(i+1 + "番目の処理が完了!!" + "待ち時間は" + n + "秒!!") 
        return 
    })) 
    console.log("終了!!") 
} 
 
// 実行 
// awaitはトップレベルで使うことができない(ES2017時点)ので 
// asyncをつけた即時関数を作って呼び出している 
(async ()=>{ 
    console.log("非同期的に呼び出す") 
    await asyncLoop() 
}).call() 
1番目の方法は次のループの処理をブロッキングしてしまうので、基本的には2番目の方法を使っておいて、どうしても非同期処理の実行順序を制御したいときのみ1番目の方法を使うのが、性能的な面で良いと思います。

以上

コメント

このブログの人気の投稿

投稿時間:2021-06-17 05:05:34 RSSフィード2021-06-17 05:00 分まとめ(1274件)

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2020-12-01 09:41:49 RSSフィード2020-12-01 09:00 分まとめ(69件)