ホームページ  >  記事  >  ウェブフロントエンド  >  Promise が setTimeout() よりも速い理由の詳細な分析

Promise が setTimeout() よりも速い理由の詳細な分析

青灯夜游
青灯夜游転載
2021-02-04 16:04:401610ブラウズ

Promise が setTimeout() より速いのはなぜですか?次の記事ではその理由を分析します。一定の参考値があるので、困っている友達が参考になれば幸いです。

Promise が setTimeout() よりも速い理由の詳細な分析

関連する推奨事項: 「JavaScript ビデオ チュートリアル

1. 実験

実験をしてみましょう。すぐに解決される Promise と即時 setTimeout (つまり、setTimeout 0 ミリ秒) のどちらが速く実行されますか?

Promise.resolve(1).then(function resolve() {
  console.log('Resolved!');
});

setTimeout(function timeout() {
  console.log('Timed out!');
}, 0);

// 'Resolved!'
// 'Timed out!'

promise.resolve(1) はstatic すぐに解決される promise を返す関数。 setTimeout(callback, 0)0 ミリ秒 の遅延でコールバック関数を実行します。

最初に 'Resolved!' が出力され、次に Timeout completed! が出力されることがわかります。すぐに解決される Promise は、即時 setTimeout

は、Promise.resolve(true).then(...)setTimeout(..., 0) より前に呼び出されたため、Promise プロセスはもっと速いですか?公正な質問です。

それでは、実験条件を少し変更して、setTimeout(..., 0):

setTimeout(function timeout() {
  console.log('Timed out!');
}, 0);

Promise.resolve(1).then(function resolve() {
  console.log('Resolved!');
});

// 'Resolved!'
// 'Timed out!'

setTimeout(..., 0) を呼び出してみましょう。 )Promise.resolve(true).then(...) の前に呼び出されます。ただし、Resolved! が最初に出力され、次に 'Timed out!' が出力されます。 ######どうしてこれなの?

2. イベント ループ

非同期 JS に関する質問は、イベント ループを学習することで解決できます。非同期 JS がどのように動作するかの主要コンポーネントを確認してみましょう。

[外部リンク画像の転送に失敗しました。ソース サイトにはリーチ防止メカニズムがある可能性があります。画像を保存して直接アップロードすることをお勧めします (img-Lt9zVHTf-1611275604640)(/img/bVcMQaI)]

Call stack

は、コードの実行中に作成された実行コンテキストを格納する LIFO (後入れ先出し) 構造です。簡単に言えば、コール スタックはこれらの関数を実行します。 Web API では、非同期操作 (フェッチ リクエスト、プロミス、タイマー) とそのコールバックが完了を待機します。

**タスク キュー (タスク キュー)

は、実行準備ができている非同期操作のコールバックを保存する

FIFO (先入れ先出し)** 構造です。たとえば、タイムアウトした setTimeout() のコールバック関数や、実行準備ができたクリック ボタン イベント ハンドラは、タスク キューにキューイングされます。 **ジョブ キュー (ジョブ キュー)** は FIFO (先入れ先出し) 構造で、実行準備が整った

promise

のコールバックを保存します。たとえば、完了した Promise の resolve または reject コールバックはジョブ キューに入れられます。 最後に、イベント ループはコール スタックが空かどうかを永続的に監視します。コール スタックが空の場合、イベント ループはジョブ キューまたはタスク キューを調べ、実行の準備ができているコールバックをコール スタックにディスパッチします。

3. ジョブ キューとタスク キュー

この実験をイベント ループの観点から見て、コードの実行を段階的に分析していきます。

A) コール スタックは

setTimeout(..., 0)

を実行し、タイマー timeout() をスケジュールします。コールバックは Web API に保存されます。 [外部リンク画像の転送に失敗しました。ソース サイトにはリーチ防止メカニズムがある可能性があります。画像を保存して直接アップロードすることをお勧めします (img-SLk0AUa5-1611275604642)(/img/bVcMQdg)]

[外部リンク画像 転送に失敗しました。ソース サイトにはリーチ防止メカニズムがある可能性があります。画像を保存して直接アップロードすることをお勧めします (img-Zr7usYTK-1611275604643)(/img/bVcMQc9)]

B) スタック実行を呼び出します

Promise.resolve (true).then(resolve)

そして promise ソリューションを手配します。 resolved()コールバックは Web API に保存されます: [外部リンク画像の転送に失敗しました。ソース サイトにはリーチ防止メカニズムが備わっている可能性があります。画像を保存することをお勧めします。直接アップロードしてください (img-JTwSnLYS- 1611275604646)(/img/bVcMQdh)]

[外部リンク画像の転送に失敗しました。ソース サイトにはホットリンク対策メカニズムがある可能性があります。画像を保存することをお勧めします。直接アップロードしてください (img-k5cRhqzN-1611275604648)(/img/bVcMQdi )]

C) Promise はすぐに解決され、タイマーはすぐに実行されます。このようにして、タイマー コールバック

timeout()

がタスク キューに入り、promise コールバック resolve() がジョブ キュー に入ります。 [外部リンク画像の転送に失敗しました。ソース サイトにはリーチ防止メカニズムが組み込まれている可能性があります。画像を保存して直接アップロードすることをお勧めします (img-iMfLB2YJ-1611275604649)(/img/bVcMQdS)]

D ) ここからが興味深い部分です。ジョブ キュー (マイクロタスク) ) はタスク キュー (マクロ タスク) よりも高い優先順位を持っています。イベント ループは、ジョブ キューから Promise コールバック

resolve()

を取得し、コール スタックに入れます。次に、コール スタックは Promise コールバック resolve(): [外部リンク画像の転送に失敗しました。ソース サイトにはリーチ防止メカニズムが組み込まれている可能性があります。画像を作成して直接アップロードします (img-nnqfgoo1 -1611275604650)(/img/bVcMQey)]

E) 最後に、イベント ループはタイマー コールバック

timeout()

をタスク キューからデキューします。呼び出しスタック。次に、コール スタックはタイマー コールバック timeout(): [外部リンク画像の転送に失敗しました。ソース サイトにはリーチ防止メカニズムが備わっている可能性があります。画像を作成して直接アップロードします (img- Fj54WaI0-1611275604650)(/img/bVcMQeB)]

呼び出しスタックは空で、スクリプトの実行は完了しました。

概要

即時解決された Promise が即時実行タイマーよりも速く処理されるのはなぜですか?

イベント ループの優先順位が存在するため、タスク キュー (タイムアウトの setTimeout() コールバックを保存する) と比較して、ジョブ キュー (実装された Promise# を保存する) ##Callback) の方が優先されます。

元のアドレス: https://dmitripavlutin.com/javascript-promises-settimeout/

著者: Milos Protic

翻訳アドレス: https://segmentfault .com/a/1190000038769853


コンピューター プログラミング関連の知識の詳細については、

プログラミング ビデオ をご覧ください。 !

以上がPromise が setTimeout() よりも速い理由の詳細な分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はsegmentfault.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。