悩みの種であるJavaScriptの非同期処理について、感覚を掴めたような気がするので備忘録です。Qiitaの記事が非常にわかりやすかったので参照します。
JavaScriptの同期、非同期、コールバック、プロミス辺りを整理してみる - Qiita
JavaScriptの実行については次のようなことが言えるようです。
排便で例えてみます。うんちする、トイレを流す、パンツを履くの3つの動作を実行する関数で表しています。ただし、うんちをするのは非常に時間のかかる処理なので、パフォーマンス重視のために非同期関数となっています。(setTimeoutを使って非同期処理にしています。)
// unchi.js
const fireUnchi = () => {
setTimeout(() => {
console.log('うんちしました。');
}, 0)
}
const flushToilet = () => {
console.log('トイレを流しました。')
}
const wearPants = () => {
console.log('パンツを履きました。')
}
fireUnchi();
flushToilet();
wearPants();実行すると次のようになります。
$ node unchi.js
トイレを流しました。
パンツを履きました。
うんちしました。悲劇です。setTimeoutは0秒なので即座に実行されても良さそうですが、この挙動は同期処理と非同期処理実行キューへの登録する方法を掴むと理解しやすいです。
同期処理では3つの関数を順番に実行していますが、最初のfireUnchi関数が実行されたときはsetTimeoutのタイマーが登録されています。setTimeoutの第二引数には0が指定されているので0秒=即座に実行キューに登録されそうですが、同期的な処理ではタイマー登録だけです。flushToilet、wearPantsが実行キューに登録されたのでlogが表示され、同期的な処理が終了した段階で次に非同期処理が始まります。タイマー指定は0秒なので非同期処理に移ってから0秒後にfireUnchiは実行キューに登録されます。
つまり、0秒後だろうが1分後だろうが、\b同期的な処理が終了してからタイマーのカウントがスタートするので同期処理より前になることはないということですね。
非同期処理を同期的に扱う方法はcallback関数やES6から追加されたPromiseを使う方法などがありますが、それはまた別に書こうと思います。