ここ二日間、「タイムリーな setTimeout を実装するには?」を紹介する記事を見ました。 》、この記事はインタビューの質問から生まれました: setTimeout を時間どおりに実行する方法はありますか?詳細については、付録 [1] を参照してください。これを読んだ後、setTimeout 関数を詳しく調べてみたくなったので、MDN の関連ドキュメントを再度確認しました。[最小遅延 >= 4ms] と記載されていたため、setTimeout を使用して 0ms の遅延タイマーを実装することはできません。実装したい場合は、参考リンク [2] を参照してください。著者の実装アイデアは、postMessage を通じてシミュレートし、setTimeout の制限を回避して 0ms の遅延タイマーを実装することです。簡単に言うと、マクロタスクを開始してコールバックを実行することです。どのように実装されているかを見てみましょう。 (関数() { var タイムアウト = []; var messageName = "ゼロタイムアウトメッセージ"; // setTimeoutと同様だが、関数引数のみを取る。 // 時間引数なし(常にゼロ)および引数なし(クロージャを使用する必要があります) 関数setZeroTimeout(fn) { タイムアウトをプッシュします(fn); window.postMessage(メッセージ名、"*"); } 関数handleMessage(イベント) { if (event.source == window && event.data == messageName) { イベントの伝播を停止します。 タイムアウトの長さが0より大きい場合 var fn = timeouts.shift(); 関数fn(); } } } window.addEventListener("メッセージ", handleMessage, true); // ウィンドウ オブジェクトに追加したいものを 1 つ追加します。 ウィンドウをゼロタイムアウトに設定します。 })(); 作者はデモページも公開している[3]。setTimeout(0)と比較すると、私のブラウザでの実行結果は以下のようになる。
比較結果によると、setZeroTimeout は setTimeout よりも数百倍高速に実行され、大きな改善が見られます。本日お話ししたいのは、上記の方法に加えて、0 ミリ秒の遅延タイマーを実装するためにどのような他の方法が使用できるかということです。まず、カスタム タイマーが非同期であることを確認する必要があります。次に、できるだけ早く実行されるようにします。非同期性について言えば、js はいくつかのソリューションを提供しており、それを 1 つずつ検証することができます。 さまざまな実装方法について詳しく説明する前に、合意によって提供される setTimeout 比較バージョンは次のとおりです。カスタム実装スキームの実行時間を setTimeout バージョンと比較します。コードは比較的単純です。 (関数() { i = 0 とします。 定数開始 = Date.now(); 関数テスト() { i++ < 100の場合{ テストタイムアウトを設定します。 } それ以外 { console.log('setTimeout 実行時間:', Date.now() - 開始); } } テストタイムアウトを設定します。 })(); キューマイクロタスクqueueMicrotask API を使用すると、マイクロタスクを追加できます。使い方は比較的簡単です。コールバック関数を渡すだけです。具体的な実装は次のとおりです。 (関数() { 関数setZeroTimeout(fn) { キューマイクロタスク(fn); } i = 0 とします。 定数開始 = Date.now(); 関数テスト() { i++ < 100の場合{ setZeroTimeout(テスト); } それ以外 { console.log('setZeroTimeout 実行時間:', Date.now() - 開始); } } setZeroTimeout(テスト); })(); setTimeout バージョンと比較すると、最終結果は次のようになります。
この API については MDN に詳しい紹介があるので、ここでは詳しく説明しません。仕様書によると、ほとんどの場合、requestAnimationFrame() や requestIdleCallback() などの API を使用することをお勧めします。queueMicrotask はレンダリングをブロックするため、多くの場合これは良い方法ではありません。 非同期/待機async/await はフロントエンド開発者にとってすでに不可欠であり、ここでもこれを使用して次のことを実現できます。 (関数() { 非同期関数setAsyncTimeout(fn) { Promise.resolve().then(fn); } i = 0 とします。 定数開始 = Date.now(); 非同期関数テスト(){ (i++ < 100) の場合 { setAsyncTimeout(テスト) を待機します。 } それ以外 { console.log('setAsyncTimeout 実行時間:', Date.now() - 開始); } } setAsyncTimeout(テスト); })(); setTimeout バージョンと比較すると、最終結果は次のようになります。
面倒でも構わないのであれば、Promise を使用して実装することもできます。実際、それらはすべて似ており、コードが少し増えるだけなので、ここでは省略します。 メッセージチャネルMessageChannel を使用すると、新しいメッセージ チャネルを作成し、その 2 つの MessagePort プロパティを通じてデータを送信できます。MessageChannel は、ワーカー/iframe 間の通信など、ポート間の通信を実現するためのポートの概念を提供します。 (関数() { 定数チャンネル = 新しいメッセージチャンネル(); 関数setMessageChannelTimeout(fn) { チャネルポート2のpostMessage(null); } チャネル.port1.onmessage = 関数() { テスト(); }; i = 0 とします。 定数開始 = Date.now(); 関数テスト() { i++ < 100の場合{ メッセージチャネルタイムアウトを設定します(テスト)。 } それ以外 { console.log('setMessageChannelTimeout 実行時間:', Date.now() - 開始); } } メッセージチャネルタイムアウトを設定します(テスト)。 })(); setTimeout バージョンと比較すると、最終結果は次のようになります。
3 番目の方法は、MessageChannel がマクロタスクを生成するのに対し、他の 2 つの方法はマイクロタスクであるため、前の 2 つの方法よりも実行に時間がかかります。マイクロタスクが最初に実行され、メイン スレッドをブロックするため、時間がかかります。 やっとこの記事では、js が提供する非同期ソリューションに基づいた 3 つの実装方法を紹介します。実装自体は複雑ではありません。 付録【1】https://mp.weixin.qq.com/s/QRIXBoKr2dMgLob3Atq9-g これで、js で 0ms 遅延タイマーを実装するいくつかの方法についての記事は終了です。より関連性の高い js 遅延タイマー コンテンツについては、123WORDPRESS.COM で以前の記事を検索するか、次の関連記事を引き続き参照してください。今後も 123WORDPRESS.COM を応援していただければ幸いです。 以下もご興味があるかもしれません:
|
<<: CentOS 7.2 に SuPHP をインストールするための詳細な手順
>>: macOS での MySQL 8.0.16 のインストールと設定のグラフィック チュートリアル
コードをコピーコードは次のとおりです。 <!--リストタグ: <dl>: 階層リス...
目次序文1. es6の前にオブジェクトを作成する2. es6 後のクラス宣言3. クラスの継承4. ...
目次概要1. フックの呼び出し順序2. onChangesフック3. 変更検出メカニズムとDoChe...
簡単に言うと、srcは「このリソースをロードしたい」という意味で、hrefは「このリソースに関連付け...
この問題に関して、オンライン リソースをたくさん見つけました。ここにいくつかの方法を示します。コード...
1. データベースをインストールする1) yum -y install mysql-server (...
実践こそが真実をテストする唯一の方法です。この記事では、インデックスの全体的な使用法についてのみ説明...
vue2 プロジェクト開発の経験があれば、$refs に精通しているでしょう。 vue3 の急激なア...
背景:最近、同社のプロジェクトは同時実行のプレッシャーに耐えられないようなので、最適化が差し迫ってい...
目次インデックスの適切な使用1. 通常のインデックスのデメリット2. 主キーインデックスの落とし穴3...
導入された HTML タグは、必ずしも XHTML 仕様に完全に準拠しているわけではありません。実際...
ディスクを自動的に検出する構成キーの値注: このキー値は Linux プラットフォームでのみサポート...
この記事では、Dockerでイメージ情報を表示する方法を学ぶ必要があります。 1. imagesコマ...
1. CSS を使用して、小さな尖った角のチャット ダイアログ ボックスと尖った角の吹き出しを描画...
エラーの説明Docker Desktop をインストールすると、WSL2 (Windows ベースの...