22.3 非同期処理はメインスレッドで実行される

非同期処理は名前から考えるとメインスレッド以外で実行されるように見えますが、基本的には非同期処理も同期処理と同じようにメインスレッドで実行される。
例えば、setTimeout関数で登録したコールバック関数は、タイマーに登録した時間(10ミリ秒後)よりも呼び出される場合もある。
JavaScriptでは一部の例外を除き非同期処理を並行処理(concurrent)として扱う。並行処理とは、処理を一定の単位ごとに分けて処理を切り替えながら実行することである。そのため非同期処理の実行中にとても重たい処理があると、非同期処理の切り替えが遅れるという現象が発生する。これは、もし非同期処理が別スレッドで行われるならば、自由なデータへのアクセスは競合状態(レースコンディション)を引き起こしてしまうためである。
但し、非同期処理の中にもメインスレッドとは別のスレッドで実行できるAPIが実行環境によっては存在する。例えばブラウザではWeb Worker APIを使い、メインスレッド以外でJavaScriptを実行できる。このWeb Workerにおける非同期処理は並列処理(Parallel)である。並列処理とは、排他的に複数の処理を同時に実行することである。Web Workerではメインスレッドとは異なるWorkerスレッドで実行されるため、メインスレッドはWorkerスレッドの同期的にブロックする処理の影響を受けにくくなる。但し、Web Workerとメインスレッドでのデータのやり取りにはpostMessageというメソッドを利用する必要がある。そのため、setTimeout関数のコールバック関数とは異なりデータへのアクセス方法にも制限がつく。
非同期処理のすべてをひとくくりにはできないが、基本的な非同期処理(タイマーなど)はメインスレッドで実行されているという性質を知ることは大切である。JavaScriptの大部分の非同期処理は非同期的なタイミングで実行される処理であると理解しておく必要がある。