6
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

あなたの知らないasync/await。並列を例に。

Posted at

async/awaitとは。

awaitはpromiseの実行結果を待つ処理です。
待つ場所、つまりはawaitの場所で、処理は直列にも並列にもなります。

何を言っているか伝わらないと思いますので、コードを示します。

サンプルコード

parallel_serial.js
function waitASecond(message) {
    return new Promise((resolve) => {
        setTimeout(() => resolve(message), 1000);
    })
}
const num = ["one", "two", "three", "four"]
const result = [];
const parallel = () => {
    for (var i in num) {
        result.push(waitASecond(num[i]));
    }
    result.forEach(async (a) => console.log(await a));
};
const serial = async () => {
    for (var i in num) {
        result.push(await waitASecond(num[i]));
    }
    result.forEach((a) => console.log(a));
};
process.on('exit', function (code) {
    console.timeEnd("four");
});
console.time("four");
if (process.env.P) {
    console.log("parallel");
    parallel();
} else {
    console.log("serial");
    serial();
}

キモ

waitASecond

waitASecondは処理に1秒かかる関数です。本番では、例えばDB接続だったり、他サーバへのHTTP通信だったりを想定してください。

parallel / serial

双方の関数とも、waitASecondを4回呼びます。ただし、awaitする場所が違います。
parallelは、waitASecondの呼び出し時にはawaitせず、最後の出力時に待ちます。

parallel
for (var i in num) {
    result.push(waitASecond(num[i]));
}
result.forEach(async (a) => console.log(await a));//←ここでawait

そして、serialはwaitASecondの呼び出し時にawaitします。

serial
for (var i in num) {
    result.push(await waitASecond(num[i]));//←ここでawait
}
result.forEach((a) => console.log(a));

これが2つの関数の違いです。

処理実行

P=true node parallel_serial.js としたときは並列実行され、実行結果は以下、

parallel
one
two
three
four
four: 1012.967ms

1秒くらいで終わってますね。

node parallel_serial.js としたときは直列実行され、実行結果は以下です。

serial
one
two
three
four
four: 4019.300ms

4秒くらいかかってます。

解説

parallelは、waitASecondの呼び出し時にはawaitしていません。
したがって、waitASecondの呼び出しは並列で4つ実行が開始されます。
出力時に、awaitによって処理が終わった順に出力されます。
したがって、1秒くらいで処理が終わっています。

serialはwaitASecondの呼び出し時にawaitしているので、4回呼び出しの一回一回の完了まで待ちます。4回処理が終わってから、出力処理に入ります。
したがって、処理に4秒くらいかかります。

まとめ

awaitは、関数の呼び出し時にしなければならないわけではありません。任意のタイミングで可能で、場所によっては並列処理に使えます。
awaitをどこですべきかを考えると、より良い実装につながることがあります。

ご参考ください。

6
9
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
6
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?