以下の 2 つのコード スニペットの違いを見つけられますか:
function handleClick1() { setTimeout(handleClick1, 0); } function handleClick2() { Promise.resolve().then(handleClick2); }
どちらかを選択した場合の影響を特定できない場合は、このブログ投稿で新しいことを学ぶことができます。
setTimeout は、一定の時間が経過した後のコールバックをスケジュールするためのものです。 Promise.resolve().then は同じことを効果的に実行しますが、内部的には両方とも異なります。後者は、すでに解決された Promise を返します。その Promise で then(callback) を呼び出すと、コールバックの実行がスケジュールされます。
したがって、上記の両方の関数は、遅延を最小限に抑えて再帰的に自分自身を呼び出します。違いは、setTimeout からのコールバックはマクロタスク キューに配置され、promise.then() からのコールバックはマイクロタスク キューに配置されることです。イベント ループがこれら 2 つのキューからのアイテムをどのように処理するかが、上記の 2 つのコード スニペットの違いとなります。
イベント ループが行うことは、実行するタスクがある間はそれを実行し、その後スリープして他のタスクを待つことだけです。
マクロタスク (または単にタスク) には、次のような作業を担当する関数が含まれます。
特に...
タスクキューから選択されたタスクの実行後、イベントループはマイクロタスクチェックポイントを実行します。アルゴリズムは次のようなものです:
While microtask queue is not empty, pick the oldest task from microtask queue and execute it.
これが意味するのは、マイクロタスクが別のマイクロタスクをキューに入れると、そのタスクは次のマクロタスクの前に実行されるということです。また、UI レンダリングはマクロタスクであるため、イベント ループによって実行されることはありません。
これは上記のデモです: JS Bin デモ。無限アニメーションが実行されます。 handleClick1 をトリガーすると、メイン スレッドに処理が追加されますが、アニメーションは引き続き正しくレンダリングされます。ただし、handleClick2 をトリガーすると、アニメーションが停止します。
変数 totalCount を追加したので、ページがクラッシュする前に中断できるようになります。しかし、注目に値するのは、microTask ループが開始されると、UI がしばらく応答しなくなることです。レンダリングや DOM への反応などのタスクは、microtask キューが空になった後にのみ実行されるためです。
これにより、上記のコード スニペットの handleClick1 がより安全な選択肢になります。このブログが、マイクロタスクとマクロタスクの基本的な違いの 1 つを説明するのに役立つことを願っています。
以上がUI ブロック動作: マイクロタスクとマクロタスクの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。