非同期処理に係る処理の個人メモ
ブラウザ環境を構成する4つの要素
- コールスタック
- WebAPI
- タスクキュー
- イベントループ
コールスタック
現在実行中の関数を追跡する仕組み。
V8などのJavaScriptエンジンの一部の機能。
関数が呼ばれたら、コールスタックに入れる。
コールスタックの中に入った処理は1つずつ1スレッドで処理される。
WebAPI
ブラウザが提供する様々な機能のことでブラウザ自体が処理をする
- setTimeout
- setInterval
- fetch
- Promise
- DOM
上にあげた処理はブラウザ自体が処理している。つまり上にあげた処理はJavasciptエンジンからは完全に切り離されて実行している。
ここが一番大事!
タスクキュー
実行待ちのタスクを格納するキューのこと。
非同期処理をタスクとして、タスクキューに追加していく。
タスク一覧
- script要素内で定義されたJavascriptコード
- イベントのコールバック関数
- setTimeoutなどのWeb APIのコールバック関数
イベントループ
タスクキューに入っているタスクを順番に処理していく仕組み。
定期的にコールスタックの中身を確認し、中身が全部なくなったタイミングで、タスクキューに格納されたタスクを実行する。
コールスタックを見張って、コールスタックが何も処理をしていないとわかったら、どんどんタスクを追加させている。
マイクロタスク
@junerさんから教えていただいたqueueMicrotask() に関する以下ページを参照して、マイクロタスクという存在を知れたのでメモ。
- JavaScriptのイベントループ内で高い優先度を持つタスクのこと
- 通常のタスクはタスクキューに入れられた順番で処理されるが、マイクロタスクは、現在処理されているタスクが終了したら(コールスタックの中身が空になったら)、すぐに実行される。
- 再描画処理よりも優先度が高い。
- タスクキューのようにマイクロタスク用のキューが存在
- Promiseのコールバック関数などがマイクロタスクキューに格納される
queueMicrotask()
- 指定したコールバック関数をマイクロタスクキューに格納するための関数。
- マイクロタスクキューに格納されたマイクロタスク(コールバック関数)は、同期的なコード実行が終わった後に実行される
イベントループはマイクロタスクキューが空になるまでマイクロタスクを実行する。
そしてqueueMicrotask()から別のqueueMicrotask()を呼び出すことができる。
つまりマイクロタスクを再帰的に格納し続けることで、タスクが実行されないというリスクがある。
console.log("開始");
queueMicrotask(() => {
console.log("マイクロタスク1");
});
console.log("中間");
queueMicrotask(() => {
console.log("マイクロタスク2");
});
console.log("終了");
// 開始
// 中間
// 終了
// マイクロタスク1
// マイクロタスク2
queueMicrotaskとsetTimeoutの違い
- 優先度が違う。
queueMicrotask > setTimeout
- queueMicrotaskのコールバック関数は、マイクロタスクキューに格納される
- setTimeoutのコールパック関数は、指定時間経過後にタスクキューに格納される
console.log('開始');
setTimeout(() => {
console.log('タイムアウト');
}, 0);
queueMicrotask(() => {
console.log('マイクロタスク');
});
console.log('終了');
//開始
//終了
//マイクロタスク
//タイムアウト