async/awaitとは。
awaitはpromiseの実行結果を待つ処理です。
待つ場所、つまりはawaitの場所で、処理は直列にも並列にもなります。
何を言っているか伝わらないと思いますので、コードを示します。
サンプルコード
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せず、最後の出力時に待ちます。
for (var i in num) {
result.push(waitASecond(num[i]));
}
result.forEach(async (a) => console.log(await a));//←ここでawait
そして、serialはwaitASecondの呼び出し時にawaitします。
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をどこですべきかを考えると、より良い実装につながることがあります。
ご参考ください。