この記事を読むにあたって以下の前提知識を踏まえていると、より理解しやすいと思います。
- javascriptでアロー関数の書き方を理解している。
-
async
,await
を使用した非同期処理を理解している。 - node.jsの実行環境でjavascriptをコードを動かしたことがある。
- typescriptであればplaygroundを使用したことがある。
- typescriptの基本的な文法と理解している。
今回書いたコードはtypescript playgroundで確認できます。 🤭
実行環境
typescript
結論
-
並列処理のメリット
- 総合的な処理が早い
-
並列処理のデメリット
- 並列で走りたい処理が多い場合、通信先のサーバーへの負荷が重くなる。
- 通信先のAPIサーバーのスペックが小さい場合、レスポンスが不安定になりエラーが返却されてしまう。
-
直列処理のメリット
- APIを叩く場合、通信先のサーバーに負荷を軽減できる。
-
並列処理のデメリット
- 総合的な処理時間がかかる。
用意
並列、直列時の実行時間を検証してみます。
まず、決められた秒数で待機するスリープ関数を定義します。
const sleep = async (msec:number):Promise<void> => new Promise((resolve) => {
setTimeout(() => {
resolve()
},msec)
引数にミリ秒を入れることによって、その時間だけ待ってくれます。
並列、直列処理で各自で実行時間を検証します。
ここでは処理時間が1,2,3秒かかる関数を3つ用意します。
それでは並列処理から見てみましょう。
並列処理をする際は、Promise.all
を使用します。引数は非同期関数の配列になります。
並列処理をする方法はPromise.all
,Promise.any
,Promise.allSettled
の三つの方法があります。
それぞれ、返却された非同期関数の値によって実行結果が変わりますがここでは説明を割愛させていただきます。
実務ではPromise.all
を使用することが多いです。
並列処理
非同期関数を実行する際は即時実行関数
でラップして動かします。
(async () => {
const start = performance.now();
await Promise.all([sleep(1000), sleep(2000), sleep(3000)])
const end = performance.now();
console.log(`process all executed executed time ${end - start} mili second`)
})();
実行した際に実行時間を計測してみます。
実行時間は3秒ほどでした。
並列処理だとPromise.all
の引数の関数が一斉に動作します。
そのため、実行時間は一番時間のかかるsleep(3000)
の3秒になります。
直列処理
並列処理と同様、非同期関数を実行する際は即時実行関数
でラップして動かします。
また直列処理は、for文
を使用して行うことができます。
(async () => {
const start = performance.now();
for (const sec of [1000,2000,3000]) {
await sleep(sec)
}
const end = performance.now();
console.log(`process all executed executed time ${end - start} mili second`)
})();
実行した際に実行時間を計測してみます。
実行時間は6秒ほどでした。
直列処理は次の関数の処理が行われないと、後続の処理が走らないようになっています。
そのため1回目の関数で1秒、2回目の関数で2秒、3回目の関数で3秒で合計6秒かかったことになります。
徒競走で例えると並列処理がヨーイドン!っで一斉スタート、直列処理がリーレー競争みたいなイメージです。参考までに。