フロントエンドインタビューの質問:JavaScriptイベントループ(イベントループ)、マクロタスクおよびマイクロタスク


イベントループ

Jsエンジンがシングルスレッドであることは誰もが知っています。つまり、一連のプログラムを実行するたびに、一方を実行してからもう一方を実行する必要があります。次に、誰かが尋ねる可能性があります。通常、setTimeoutタイマーをオンにしますが、次のプログラムの動作に影響はありません。これは、JavaScriptが開始以来、シングルスレッドのノンブロッキングスクリプト言語であったためです。そして、その非ブロッキングは非同期タスクによって実現されます。setTimeoutが非同期タスクであることがわかります。

次に、上の図からわかります。非同期タスクを実行するには、ブラウザーの組み込みwebAPIモジュール(ブラウザーのサブスレッド)を使用して非同期タスクを実行する必要があります。


setTimeout(()=>{
    
    
	console.log('我是异步')
},2000)
console.log('我是同步')

上記のコードの実行プロセス:

  1. ブラウザがJsコードをsetTimeout関数に解析する入栈と、関数は関数が非同期コードであることを検出し、それを放入webAPIsブラウザスレッドに分割します开始计时
  2. ブラウザはJsコードconsole.log('我是同步')を続行し、それが同步コードであることを検出し直接、スタックをポップして执行「Iamsynchronous」を出力します。
  3. ほぼ2秒後、ブラウザーはスレッド(webAPI)を分割し、終了したタイマー関数をcallback queueコールバックキュー(メッセージキュー)に入れ、ブラウザーはコールバックキューのトラバースを開始し、タイマー関数をスタックに入れてすぐに実行します。コンソール印刷「私は非同期です」

この操作により、イベントループが完了します。

注:ブラウザーは、実行スタックに実行されるプログラムがない場合にのみコールバックキューをポーリングします(コールバックキューにコールバック関数がある場合は、実行のために実行スタックにプルします)

2.マクロタスク/マイクロタスク

非同期コードの実行順序は異なり、上から下に1つずつ実行されるわけではありません。非同期機能はマクロタスクとマイクロタスクに分かれているためです。
実行順序は、同期タスク->非同期マイクロタスク->非同期マクロタスクです。

マクロタスク:

  1. 新程序或子程序被直接执行
  2. 时间的回调函数
  3. setTimeout和setInterval的回调

マイクロタスク1。2.3
Promise.then() .catch() .finally()
MutationObserver
Object.observe

レンダリングなし

// 宏任务
console.log('1')

// setTimeout 的回调是 宏任务,进入回调队列排队
setTimeout(() => {
    
    

    // 宏任务
    console.log('4')
    
    // setTimeout 的回调是 宏任务2,进入回调队列排队
    setTimeout(() => {
    
    
        console.log('7')
    }, 0)
    
    // Promise 的回调是 微任务,本轮调用末尾直接执行
    Promise.resolve()
        .then(() => {
    
    
            console.log('6')
        })
    console.log('5')
}, 0)

// Promise 的回调是 微任务,本轮调用末尾直接执行
Promise.resolve()
    .then(() => {
    
    
        console.log('3')
    })
    
console.log('2')

上記のコード実行シーケンスは、1〜7個の正のシーケンス出力です。

各マクロタスクの後にマイクロタスクキューを続けることができます。マイクロタスクキューに命令またはメソッドがある場合は実行されます。ない場合は、すべてのマクロタスクが実行されるまで次のマクロタスクが実行されます。タスクは次のとおりです。マクロタスクのスモールテールに相当します。
したがって、これはコールバックキューのファーストイン、ファーストアウトの原則に違反しません。マクロタスクにマイクロタスクが付随している場合、マイクロタスクが最初に実行されます。マクロタスクが最初に配置され、次のマイクロタスクが待機されます。すべてが実行されたら、マクロタスクの実行を再開してください。


実際、Jsコードのブラウザー実行の完全なシーケンスは次のようになります。同期タスク->非同期マイクロタスク-> DOM渲染页面->非同期マクロタスク

そうです、マイクロタスクとマクロタスクの間で、ブラウザは次の場合のようにDOMレンダリングを実行します。

レンダリングあり

//向body添加h1节点,内容为Hello
const $content = $('<h1>Hello</h1>')
$('body').append($content)

console.log(1);

Promise.resolve().then(() => {
    
    
    console.log('2.promise');
    alert('promise then')
})

setTimeout(() => {
    
    
    console.log('3 setTimeout');
    alert('setTimeout')
}, 0);

console.log(4);

実行プロセス:
ステップ1 :
ここに画像の説明を挿入
アラートウィンドウをクリックして確認した後、ステップ2:
ここに画像の説明を挿入
これは結論を証明します:同期タスク->非同期マイクロタスク-> DOM渲染页面->非同期マクロタスク

おすすめ

転載: blog.csdn.net/weixin_60297362/article/details/123298178