Open7

【JS】非同期まとめ

snunsu:<esnunsu:<e

V8エンジンについて

  • 非同期について考えようと思った
  • V8エンジンのソースをグレップしても
    • setTimeout
    • DOM
    • HTTP
  • などが見当たらなかった
  • これらはWEBブラウザから提供されているものだった
snunsu:<esnunsu:<e

JavaScriptはシングルスレッドである

  • 基本的にコールスタックで実行している
  • コールスタックとは基本的に「プログラミングの何処にいるのか」を記録するデータ構造である
snunsu:<esnunsu:<e

ブロッキングについて

  • 処理が重いものをシングルスレッドで実行すると他に何も出来なくなる
  • 講義の例では、重いHTTP通信をあげている
  • 開くのに5秒くらいかかるリンクを押下すると、その間は何も出来なくなる
  • これをブロッキングされている状態とする
snunsu:<esnunsu:<e

asyncについて

  • ブロッキングの解決策として同期処理がある

console.log('hi');

setTImeout(function(){
    console.log('there');
},5000)


console.log('china');
  1. 最初に、コードは上から順に実行されるため、console.log('hi');がコールスタックにプッシュされ、"hi"がコンソールに表示されます。
  2. 次に、setTimeout関数がコールスタックにプッシュされます。しかし、setTimeoutは非同期関数であり、指定された時間(この場合は5000ミリ秒)が経過するまで実行を遅延させます。setTimeout関数はコールスタックからポップされ(これはV8エンジンではなく、ブラウザ側のAPI or 環境によってはNode.jsのAPIなど)、タイマーがスタートします。
  3. console.log('china');がコールスタックにプッシュされ、"china"がコンソールに表示されます。
  4. 指定された時間が経過すると、setTimeoutのコールバック関数がタスクキューに追加されます。
  5. イベントループはコールスタックが空になったのを確認して 、タスクキューからコールバック関数を取り出し、コールスタックにプッシュします。
  6. 最後に、コールバック関数内のconsole.log('there');がコールスタックにプッシュされ、"there"がコンソールに表示されます。
snunsu:<esnunsu:<e

コールスタックが空じゃなかったら?(脱線)

※本講義の内容ではありません

  • コールスタックが空じゃなかったら

タスクキューからコールバック関数を取り出し、コールスタックにプッシュします。

  • この動作は行いません
  • つまり、setTimeoutはあくまでも「指定された遅延時間(この場合は5秒)が経過した後に、そのコールバック関数をタスクキュー(またはコールバックキュー)に追加」するのであって、「5秒後に実行される」のではないということ
snunsu:<esnunsu:<e

マイクロタスクとマクロタスク

マクロタスク→タスクキュー

  • 主にイベントループの各サイクルで処理されるタスク

主なタスク

  • setTimeout
  • setInterval
  • setImmediate (Node.js環境)
  • I/O
  • UIレンダリング
  • requestAnimationFrame (ブラウザ環境)

実行のタイミング

  • 順番が回ってきたら全て

マイクロタスク→ジョブキュー

  • より細かい非同期タスク

主なタスク

  • Promiseのthen、catch、finallyハンドラ
  • MutationObserver (ブラウザ環境)
  • process.nextTick (Node.js環境)
  • queueMicrotask (ブラウザ環境)

実行のタイミング

  • 順番が回ってきたら一個ずつ