新しいことにはウェルカム

技術 | 電子工作 | ガジェット | ゲーム のメモ書き

JavaScriptで同時実行数を指定しつつ並行実行させる方法

沢山のタスクがあって並行処理したいのですが、全てを並行実行させると重くなってしまうので、同時実行数を指定しつつ並行実行させたい時があります。

恥ずかしながらJavaScriptでそれをやる方法を知らず、代案として、処理したいタスクを同時実行数づつに分けて、一まとまりをPromise.all()で実行していました。

しかしこれだと、一まとまりのPromise.all()に入れたタスクが全て終了してから、次の一まとまりの処理を行うので、常に一定数の同時実行ではないのでモヤモヤしていたのですが、JavaScritで同時実行数を指定しつつ並行実行させる記事を見つけました。

qiita.com

qiita.com

なるほど~。同時実行数だけPromiseを起動して、そのPromiseの中でタスクを実行すればいいんですね。

いや~、勉強になりました!

ずっとモヤモヤしていたのが解決してスッキリしました!ありがとうございます。

写経

実際に手を動かさないと身につかないので、記事を参考にリライトしてみました。

function task(workerId: number, dataId: number, input: number) {

    return new Promise((resolve, reject) => {
        console.log(`TASK START : workerId->${workerId} dataId->${dataId} input->${input}`);
        setTimeout(() => {
            console.log(`----- TASK END : workerId->${workerId} dataId->${dataId} input->${input}`);
            resolve({
                workerId,
                dataId,
                input,
                result: input * 10,
            });
        }, input * 1000);
    });
}

(async () => {

    // promise間で共有するデータ
    const data = [4, 3, 2, 1, 0, 3, 2, 1]; // 処理するデータ
    let dataIdx = 0; // 処理位置

    const workerNum = 3; // 同時実行数
    const workers = [];
    for (let workerIdx = 0; workerIdx < workerNum; workerIdx++) {

        const p = new Promise(async (resolve, reject) => {

            const results: any = [];
            while (dataIdx < data.length) {
                const idx = dataIdx;
                dataIdx++;  // awaitの前にインクリメントする
                const res = await task(workerIdx, idx, data[idx]);
                results.push(res);
            }

            resolve(results);

        });

        workers.push(p);
    }

    // 終了待ち
    const res = await Promise.all(workers);

    // 結果取得
    for (const p of res) {
        for (const v of (p as any)) {
            console.log(v);
        }
    }
})();

ポイントとしては、同時実行数だけPromiseを作成して、そのPromise間で入力データを共有させるところでしょうか。

注意点としては、タスクは非同期実行されるので、タスク関数を呼び出す前に、処理位置を進めておくのを忘れずに。

感想など

今回の例は、入力データ数が決まっている場合のみ有効で、ストリームなど、データ数が未定の場合には使えません。何とかできないかと色々試してみましたが挫折しました…。

関連カテゴリー記事

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com