BLOG

非同期処理メモ⑩

おはようございます。

今日からモーニングルーティンをアップデートしてしっかり朝活取り組んでおりますどうもハヤトワンです。

さて、非同期処理のマイクロタスクとマクロタスクについて、昨日の補足をしていきます。

▼マイクロタスク

順番が回ってきたら全てのジョブを実行する。

▼マクロタスク

順番が回ってきたら1つずつタスクを実行

例:

コールスタック:context

マイクロタスク(ジョブキュー):ジョブ1、ジョブ2

マクロタスク(タスクキュー):タスク1、タスク2

があったとする。

そして、まずコールスタックがなくなると、

マイクロタスクのジョブが全て終了してから、マクロタスクの中のタスクが1つだけ実行される

コールスタック:context

マイクロタスク(ジョブキュー):ジョブ1、ジョブ2

マクロタスク(タスクキュー):タスク1、タスク2

そしてこの間に、マイクロタスクの中にさらにジョブ3、ジョブ4の2つが追加された場合、

マイクロタスクのジョブを2つ実行してから、マクロタスクに格納されているタスク2が実行されることになる。

コールスタック:

マイクロタスク(ジョブキュー):ジョブ3、ジョブ4

マクロタスク(タスクキュー):タスク2

これがマイクロタスクとマクロタスクの挙動の違い。

この場合はどうなるか

new Promise(function promise(resolve) {
  console.log('promise');

  setTimeout(function task1() {
    console.log('タスク1');
    resolve();
  });
}).then(function job1(){
  console.log('ジョブ1')
});

console.log('global end');

コンソール

promise
global end
タスク1
ジョブ1

になる。

まず最初に同期的に実行されるPromiseのconsole.log

これ以外はsetTimeoutやthenの中は非同期処理になるので、次に出力されるのはconsole.log(‘global end’)になる。

今回の場合、setTimeoutの中にresolveがあるため、resolveの実行を待つthenメソッドのコールバック関数は一番最後に実行されることになる。

登場人物

・コールスタック

・非同期API

・マイクロタスク(ジョブキュー)

・マクロタスク(タスクキュー)

まずスクリプトが実行されると、グローバルコンテキストからNew Promiseの中のコールバック関数のPromiseが実行される

このPromiseの中でsetTimeoutが呼ばれ、このsetTimeoutのコールバック関数の中でresolve()が呼ばれる。、そしてPromiseのthenメソッドのコールバック関数であるジョブ1がresolveを待つ待機状態になる。(非同期APIの中)

次にsetTimeoutのコールバック関数である、タスク1がマイクロタスクに格納される。

そしてコールスタックがはけていくと、(promise、グローバルがなくなる)このときにはマイクロタスク(ジョブキュー)にはなにも格納されていないので、マクロタスク(タスクキュー)のタスク1がコールスタックに移動することになる。

このタスク1の中にはresolve()を保持しているので、このresolveが実行されたときにthenメソッドが呼ばれ、マイクロタスクにジョブ1が登録される。

そしてコールスタックがもう一度はけると(タスク1とresolveがなくなる)、次はジョブ1がコールスタックに上がってくるため、一番最後にジョブ1が上がってくる。

setTimeoutの中でresolveが呼ばれた場合はこのようなイメージを持つといい。

ふむふむ。

順番がしっかりあるんですね〜。

てことで続きはまた明日。

今日もいい1日を!