JavaScriptのマクロタスクとマイクロタスク

5944 ワード

フロントエンドのマクロタスクとタスクを紹介する前に、まず問題を並べてみます.
console.log('1')
setTimeout(() => {
  console.log('2')
})
new Promise((resolve, rejects) => {
  console.log('3')
  resolve()
}).then(() => {
  console.log('4')
})
console.log(5)
まず自分の答えを出して、結果を実行してみてください.自分の考えと一致するかどうかを確認してください.
1.基本概念
ここではJavaScriptの中の基本的な知識を紹介します.
  • コード実行環境については、JavaScriptコード実行時にエンジンが現在のコードブロックの実行環境を作成します.変数の使用に関しては、現在の環境の変数と現在の実行環境を含む外部環境変数のみが検索されます.グローバル環境は最外層の実行環境である.
  • JavaScriptはシングルスレッドです.
  • JavaScriptは、非同期動作を処理する際に、イベントサイクル機構を利用する.
  • 2.マクロタスク、マイクロタスクとイベント循環メカニズム
    事件の循環を知っている学生はすべて知っていて、事件の循環の中で、非同期の事件は現在の任務の実行の隊列に置くことはできなくて、保留されることができるので、別の回転行列に入れます.現在のジョブキューの実行が終了した後、JavaScriptエンジンが戻り、実行待ちのタスクがあるかどうかを確認し、最初のタスクを実行キューに追加して、このプロセスを繰り返します.
    現象的には、マクロタスクとマイクロタスクから生じる非同期の操作は、実行キューが完了した後に実行されるので、マクロタスクとマイクロタスクはすべてコールバックキューに配置されているようです.
    本当にそうですか?
    違います.もしそうなら、マクロタスクとマイクロタスクは意味的には区別されません.
    3.マクロタスクとタスク
    まず私達は必ず堅持します.マクロタスクとマイクロタスクは意味的には絶対区があります.
    ブラウザ環境でマクロタスクをトリガできる操作にはどのようなものがありますか?
  • I/O操作
  • setTimeout
  • set Interval
  • request Animation Frame(議論、後述する)
  • setTimeoutを例にとる.JavaScriptはシングルスレッドなので、setTimeoutのタイミング操作はJavaScriptではないはずです.そうでないとコードの実行が滞ります.
    この操作は誰がやりますか?宿主環境です.ブラウザを例にとって、JavaScriptはsetTimeoutまで実行する時にブラウザに教えます.「Hey boy!これはタイマーがあります.ポイントを見てください.後で教えてください.」この時にブラウザでは、タイムアウトが完了したら、JavaScriptイベントサイクルのコールバックキューにセットTimeoutのコールバックを入れます.このように JavaScriptは次の実行中にこのフィードバックを処理することができます.
    上記の4点のマクロタスクをトリガする操作を見てみます.すべてブラウザと関連しています.
    だから、私の個人的な理解は、マクロタスクは JavaScriptと宿主環境から生じるコールバックは、宿主環境協力処理が必要であり、また、コールバックキューに入れられるタスクはすべてマクロタスクである.
    ブラウザでマイクロタスクを起動する操作は以下の通りです.
  • Promise
  • MuttionObserver
  • この二つの操作も非同期操作ができるのですが、なぜマクロタスクとは違っていますか?ここではイベントサイクルのもう一つの列に関連します.作業キュー(マイクロタスクキュー).
    作業キューをよりよく理解するために、実行キューを開始してから終了するまでのプロセスを一つのtickといい、整列キューの最初のイベントは次のtickで実行され、二つ目のイベントは次のtickで順次実行されます.
    作業キューは、現在のtickの最後尾に位置しており、現在のtickに加えられたマイクロタスクは、次のtickには残らず、tickの末尾にトリガして実行されます.
    一つのイベントサイクルでは、実行待ち行列のタスクが実行された後、単独のステップがあります.Perform a microtask checkpointといいます.つまり、マイクロタスクチェックポイントを実行します.この操作は、作業キューにジョブがあるかどうかを確認し、ある場合は作業チームも実行キューとして実行し、終了後は実行キューを空にします.
    したがって、ここでは、同じ実行キューによって生成されるマイクロタスクは、常にマクロタスクの前に実行されるということを確認することができます.
    じゃ、私達は今3時からの質問に答えます.マクロタスクとマイクロタスクの意味はどこにありますか?
    個人的な理解は、マクロタスクは、宿主環境の協力のもとで、レプリカを通じて非同期の操作を完了することができます.マイクロタスクは、マクロタスクの実行前に、いくつかの操作を行い、Javascriptエンジンが現在の実行キューを処理した後、できるだけ早くコードを実行することを伝えます.
    4.request Animation Frameについて
    最初はrequest Animation Frameの定義はマクロタスクです.request Animation Frameをテストする時には下記のコードを使いました.
    const testElement = document.getElementById('testElement')
    setTimeout(() => {
      console.log(performance.now(), 'settimeout')
    }, 0)
    requestAnimationFrame(() => {
      console.log(performance.now(),
     'requestAnimationFrame')
    })
    var observer = new MutationObserver(() => {
      console.log('MutationObserver')
    });
    observer.observe(testElement, {
     childList: true 
    })
    const div = document.createElement('div')testElement.appendChild(div)
    new Promise(resolve => {
      console.log('promise')  resolve()
    }).then(() => console.log('then'))
    console.log(performance.now(), 'global')
    ブラウザの出力に差があります.何回か運転したら、二つの結果が出ます.
    一つ目は:
    もう一つは:
    最初に私はrequest Animation Frameをマクロタスクの中に入れました.その理由はほとんどがsetTimeoutでフィードバックしてから実行します.この結果を、ブラウザがレンダリングを実行するたびに実行時間が違ってくるため、リコットAnimation Frameとset Timeoutがリセットされるタイミングが一致しないと解釈し、それによってフィードバックの時間が一致しないという結果になりました.
    しかし、この強引な説明はやはり踏み込めません.へへ、私たちは優秀なプログラマーを志す有志青年として、やはり論拠を探さなければなりません.      ----____南風です
    その後、いくつかの資料を調べましたが、この規格文書を見て、あるイベントサイクルのtickにブラウザのレンダリング過程が含まれていることが分かりました.そして、request Animation Frameのトリガはブラウザで再描画する前に、MDN文書には以下のように紹介されています.window.requestAnimationFrame()は、ブラウザに対して、アニメーションを実行したいと話し、ブラウザに対して、次の絵を描く前に指定されたコールバック関数を呼び出してアニメーションを更新するよう要求します.この方法はパラメータとしてフィードバック関数を導入する必要があります.このコールバック関数はブラウザが次の絵を描く前に実行されます.
    したがって、request Animation Frameのコールバックのタイミングも現在のtickにありますので、マクロタスクではありませんが、マイクロタスクではなく、マイクロタスクの後にあります.
    もちろん、この問題をご指導できれば、コメントエリアのコメントを歓迎します.手動で花を撒く /手動で花を撒く
    5.まとめ
    マイタスクとマクロタスクは、私が七星テントウを扱う時、偶然に接触した知識です.この文章を整理し終わって、JavaScript事件の循環に対する理解がまた少し深くなりました.この文書を読んだあなたにも助けがほしいです.ハハ.
    「JavaScriptで書いてもいいアプリケーションは、最終的にはJavaScriptで書きます.」
    補足をつける
  • Node環境下のマクロタスク:
  • I/O操作
  • setTimeout
  • set Interval
  • setImmedite
  • Node環境下のマイクロタスク:
  • Promise
  • process.nextTick
  • whileサイクルの遅延が増加しました.イベントのサイクルをより明確に感じることができます.
    console.log('1')
    setTimeout(() => {
      console.log('2')
    })
    new Promise((resolve, rejects) => {
      console.log('3')
      resolve()
    }).then(() => {
      let i = 0
      while(i < 1000000000) {
        i++
      }
      console.log('4')
    })
    let i = 0
    while(i < 1000000000) {
      i++
    }
    console.log(5)
    転載先:https://juejin.im/post/5caac21de51d452b66462649