JavaScript のタイミングメカニズムの詳細な説明 (コードを含む)
この記事では主に JavaScript のタイミングメカニズムについて詳しく紹介します。興味のある友人は参考にしてください。
この記事では、JavaScript のタイミングメカニズムを紹介します。JavaScript のタイミングメカニズムを理解するには、JavaScript の実行メカニズムを理解する必要があります。
まず、JavaScript はシングルスレッド (JavaScript エンジンのスレッド) イベント駆動型であると述べられています。
1. ブラウザーには複数のスレッドがあります
ブラウザーに含まれる最も基本的なスレッド:
1.
2. タイマー スレッド、setInterval および setTimeout がこのスレッドをトリガーします。
3. ブラウザ イベント トリガー スレッド。このスレッドは、onclick、onmousemove、その他のブラウザ イベントをトリガーします。
4. インターフェイス レンダリング スレッドは、ブラウザ インターフェイスの HTML 要素をレンダリングします。注: JavaScript エンジンがスクリプトを実行している間、インターフェイス レンダリング スレッドは一時停止状態になります。つまり、JavaScript を使用してインターフェース内のノードを操作しても、すぐには反映されません。JavaScript エンジンのスレッドがアイドル状態になるまで反映されません。 (これは最後に言います)
5. HTTP リクエスト スレッド (Ajax リクエストも含まれます)。
上記のスレッドはブラウザカーネルの制御下で相互に連携して作業を完了します(詳細はわかりません)。
2. タスクキュー
JavaScript はシングルスレッドであり、すべての JavaScript コードは JavaScript エンジン スレッドで実行されることがわかっています。 Ruan Yifeng 先生の記事では、このスレッドを実行スタックであるメイン スレッドと呼んでいます。 (以下の内容は、主にRuan Yifeng先生の記事の理解と要約に基づいています。)
これらのJavaScriptコードを1つずつタスクとして考えることができます。これらのタスクは、同期タスクと非同期タスクに分けられます。同期タスク (変数代入文、アラート文、関数宣言文など) はメインスレッド上で直接順番に実行され、非同期タスク (ブラウザのイベントトリガースレッドによってトリガーされるさまざまなイベントなど、返されたサーバー応答を使用します) Ajax などによる)は、時系列順にタスクキュー(イベントキュー、メッセージキューとも呼ばれます)にキューイングされ、実行を待ちます。メインスレッド上のタスクが実行されている限り、タスクキューがチェックされ、キュー内に待機中のタスクがあるかどうかが確認されます。存在する場合、キューに入れられたタスクは実行のためにメインスレッドに入ります。
たとえば、次の例:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>定时机制</title> <style type="text/css"> body{ margin: 0; padding: 0; position: relative; height: 600px; } #test{ height: 30px; width: 30px; position: absolute; left: 0; top: 100px; background-color: pink; } </style> </head> <body> <p id="test"> </p> <script> var pro = document.getElementById('test'); pro.onclick = function() { alert('我没有立即被执行。'); }; function test() { a = new Date(); var b=0; for(var i=0;i<3000000000;i++) { b++; } c = new Date(); console.log(c-a); } test(); </script> </body> </html>
この例では、test() 関数の実行に約 8 ~ 9 秒かかるため、このページを開いて 8 秒前にピンク色の四角をクリックすると、プロンプトが表示されますボックスはすぐには表示されませんが、ポップアップするまで 8 秒待つ必要があり、8 秒前にピンクのボックスを数回クリックすると、8 秒後に数回ポップアップします。
このページを開くと、メインスレッドは最初に関数 test を宣言し、次に変数 pro を宣言し、次に p ノードを pro に割り当て、次にクリック イベントを p ノードに追加し、コールバック関数 (一時停止) を指定します。次に、テスト関数を呼び出し、その中のコードを実行します。テスト関数のコードの実行中に、p ノードをクリックすると、ブラウザーのイベント トリガー スレッドがこのイベントを検出し、メイン スレッド (ここではテスト関数) 上のタスクが実行されるようにイベントをタスク キューに配置しました。最後に、タスク キューをチェックするときにこのイベントが検出され、対応するコールバック関数が実行されます。複数回クリックすると、これらの複数のトリガーされたイベントがトリガー時間に従ってタスク キューに入れられます (クリック イベントを別の要素に追加し、別の要素を交互にクリックして確認することができます)。
タスクの動作メカニズムをまとめると以下の通りです:
非同期実行の動作メカニズムは以下の通りです。 (同期実行についても同様です。非同期タスクがなければ非同期実行とみなすことができるためです。)
1. すべての同期タスクはメインスレッドで実行され、実行コンテキストスタックを形成します。
2. メインスレッドに加えて、「タスクキュー」もあります。非同期タスクに実行結果がある限り、イベントは「タスク キュー」に配置されます。
3. 「実行スタック」内のすべての同期タスクが完了すると、システムは「タスクキュー」を読み取り、その中にどのようなイベントがあるかを確認します。これらの対応する非同期タスクは待機状態を終了し、実行スタックに入り、実行を開始します。
4. メインスレッドは上記の 3 番目のステップを繰り返します。
3. イベントとコールバック関数
DOM 要素にイベントを指定する場合、実際にイベントが発生したときに対応するコードが実行できるようにコールバック関数を指定します。
メインスレッドのイベントのコールバック関数は、タスクキューにキューイングされている対応するイベントがある場合、メインスレッドがそれを検出したときに、対応するコールバック関数が実行されます。メインスレッドが非同期タスクを実行し、対応するコールバック関数を実行しているとも言えます。
4. イベントループ
タスクキュー内のイベントをチェックするメインスレッドのプロセスは周期的であるため、イベントループの図を描くことができます:
上图中主线程产生堆和执行栈,栈中的任务执行完毕后,主线程检查任务队列中由其他线程传入的发生过的事件,检测到排在最前面的事件,就从挂起的回调函数中找出与该事件对应的回调函数,然后在执行栈中执行,这个过程一直重复。
五、定时器
结合以上知识,下面探讨JavaScript中的定时器:setTimeout()和setInterval()。
setTimeout(func, t)是超时调用,间隔一段时间后调用函数。这个过程在事件循环中的过程如下(我的理解):
主线程执行完setTimeout(func, t);语句后,把回调函数func挂起,同时定时器线程开始计时,当计时等于t时,相当于发生了一个事件,这个事件传入任务队列(结束计时,只计时一次),当主线程中的任务执行完后,主线程检查任务队列发现了这个事件,就执行挂起的回调函数func。我们指定的时间间隔t只是参考值,真正的时间间隔取决于执行完setTimeout(func, t);语句后的代码所花费的时间,而且是只大不小。(即使我们把t设为0,也要经历这个过程)。
setInterval(func, t)是间歇调用,每隔一段时间后调用函数。这个过程在事件循环中的过程与上面的类似,但又有所不同。
setTimeout()是经过时间t后定时器线程在任务队列中添加一个事件(注意是一个),而setInterval()是每经过时间t(一直在计时,除非清除间歇调用)后定时器线程在任务队列中添加一个事件,而不管之前添加的事件有没有被主线程检测到并执行。(实际上浏览器是比较智能的,浏览器在处理setInterval的时候,如果发现已任务队列中已经有排队的同一ID的setInterval的间歇调用事件,就直接把新来的事件 Kill 掉。也就是说任务队列中一次只能存在一个来自同一ID的间歇调用的事件。)
举个例子,假如执行完setInterval(func, t);后的代码要花费2t的时间,当2t时间过后,主线程从任务队列中检测到定时器线程传入的第一个间歇调用事件,func开始执行。当第一次的func执行完毕后,第二次的间歇调用事件早已传入任务队列,主线程马上检测到第二次的间歇调用事件,func函数又立即执行。这种情况下func函数的两次执行是连续发生的,中间没有时间间隔。
下面是个例子:
function test() { a = new Date(); var b=0; for(var i=0;i<3000000000;i++) { b++; } c = new Date(); console.log(c-a); } function test2() { var d = new Date().valueOf(); //var e = d-a; console.log('我被调用的时刻是:'+d+'ms'); //alert(1); } setInterval(test2,3000); test();
结果:
为什么8.6秒过后没有输出两个一样的时刻,原因在上面的内容中可以找到。
执行例子中的for循环花费了8601ms,在执行for循环的过程中队列中只有一个间歇调用事件在排队(原因如上所述),当8601ms过后,第一个间歇调用事件进入主线程,对于这个例子来说此时任务队列空了,可以再次传入间歇调用事件了,所以1477462632228ms这个时刻第二次间歇调用事件(实际上应该是第三次)传入任务队列,由于主线程的执行栈已经空了,所以主线程立即把对应的回调函数拿来执行,第二次调用与第一次调用之间仅仅间隔了320ms(其实8601+320=8920,差不多就等于9秒了)。我们看到第三次调用已经恢复正常了,因为此时主线程中已经没有其他代码了,只有一个任务,就是隔一段时间执行一次间歇调用的回调函数。
用setTimeout()实现间歇调用的例子:
function test() { a = new Date(); var b=0; for(var i=0;i<3000000000;i++) { b++; } c = new Date(); console.log(c-a); } function test2(){ var d = new Date().valueOf(); console.log('我被调用的时刻是:'+d+'ms'); setTimeout(test2,3000); } setTimeout(test2,3000); test();
结果:
每两次调用的时间间隔基本上是相同。想想为什么?
再看一个例子:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Flex布局练习</title> <style type="text/css"> body{ margin: 0; padding: 0; position: relative; height: 600px; } #test{ height: 30px; width: 30px; position: absolute; left: 0; top: 100px; background-color: pink; } </style> </head> <body> <p id="test"> </p> <script> var p = document.createElement('p'); p.style.width = '50px'; p.style.height = '50px'; p.style.border = '1px solid black'; document.body.appendChild(p); alert('ok'); </script> </body> </html>
这个例子的结果是提示框先弹出,然后黑色边框的p元素才出现在页面中。原因很简单,就一句话:
在JavaScript引擎运行脚本期间,界面渲染线程都是处于挂起状态的。也就是说当使用JavaScript对界面中的节点进行操作时,并不会立即体现出来,要等到JavaScript引擎线程空闲时,才会体现出来。
上面是我整理给大家的,希望今后会对大家有帮助。
相关文章:
以上がJavaScript のタイミングメカニズムの詳細な説明 (コードを含む)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











顔の検出および認識テクノロジーは、すでに比較的成熟しており、広く使用されているテクノロジーです。現在、最も広く使用されているインターネット アプリケーション言語は JS ですが、Web フロントエンドでの顔検出と認識の実装には、バックエンドの顔認識と比較して利点と欠点があります。利点としては、ネットワーク インタラクションの削減とリアルタイム認識により、ユーザーの待ち時間が大幅に短縮され、ユーザー エクスペリエンスが向上することが挙げられます。欠点としては、モデル サイズによって制限されるため、精度も制限されることが挙げられます。 js を使用して Web 上に顔検出を実装するにはどうすればよいですか? Web 上で顔認識を実装するには、JavaScript、HTML、CSS、WebRTC など、関連するプログラミング言語とテクノロジに精通している必要があります。同時に、関連するコンピューター ビジョンと人工知能テクノロジーを習得する必要もあります。 Web 側の設計により、次の点に注意してください。

インターネット金融の急速な発展に伴い、株式投資を選択する人がますます増えています。株式取引では、ローソク足チャートは一般的に使用されるテクニカル分析手法であり、株価の変化傾向を示し、投資家がより正確な意思決定を行うのに役立ちます。この記事では、PHP と JS の開発スキルを紹介し、株価ローソク足チャートの描画方法を読者に理解してもらい、具体的なコード例を示します。 1. 株のローソク足チャートを理解する 株のローソク足チャートの描き方を紹介する前に、まずローソク足チャートとは何かを理解する必要があります。ローソク足チャートは日本人が開発した

JavaScript チュートリアル: HTTP ステータス コードを取得する方法、特定のコード例が必要です 序文: Web 開発では、サーバーとのデータ対話が頻繁に発生します。サーバーと通信するとき、多くの場合、返された HTTP ステータス コードを取得して操作が成功したかどうかを判断し、さまざまなステータス コードに基づいて対応する処理を実行する必要があります。この記事では、JavaScript を使用して HTTP ステータス コードを取得する方法を説明し、いくつかの実用的なコード例を示します。 XMLHttpRequestの使用

js と vue の関係: 1. Web 開発の基礎としての JS、2. フロントエンド フレームワークとしての Vue.js の台頭、3. JS と Vue の補完関係、4. JS と Vue の実用化ビュー。

JavaScript で HTTP ステータス コードを取得する方法の紹介: フロントエンド開発では、バックエンド インターフェイスとの対話を処理する必要があることが多く、HTTP ステータス コードはその非常に重要な部分です。 HTTP ステータス コードを理解して取得すると、インターフェイスから返されたデータをより適切に処理できるようになります。この記事では、JavaScript を使用して HTTP ステータス コードを取得する方法と、具体的なコード例を紹介します。 1. HTTP ステータス コードとは何ですか? HTTP ステータス コードとは、ブラウザがサーバーへのリクエストを開始したときに、サービスが

現在のページを更新する js メソッド: 1. location.reload(); 2. location.href; 3. location.assign(); 4. window.location。詳細な紹介: 1. location.reload()、location.reload() メソッドを使用して現在のページを再読み込みします; 2. location.href、location.href 属性などを設定することで現在のページを更新できます。

CSS のリフローと再描画は、Web ページのパフォーマンスの最適化において非常に重要な概念です。 Web ページを開発する場合、これら 2 つの概念がどのように機能するかを理解すると、Web ページの応答速度とユーザー エクスペリエンスを向上させることができます。この記事では、CSS のリフローと再描画の仕組みを詳しく説明し、具体的なコード例を示します。 1. CSS リフローとは何ですか? DOM 構造内の要素の表示、サイズ、位置が変更されると、ブラウザは CSS スタイルを再計算して適用し、再レイアウトする必要があります。

__proto__ とprototypeはJSのプロトタイプに関連する2つの属性で、機能が少し異なります。この記事では、2 つの違いを詳しく紹介して比較し、対応するコード例を示します。まず、それらが何を意味し、何に使用されるのかを理解しましょう。 proto__proto__ は、オブジェクトのプロトタイプを指すオブジェクトの組み込みプロパティです。カスタム オブジェクト、組み込みオブジェクト、関数オブジェクトなど、すべてのオブジェクトには __proto__ 属性があります。 __proto__属による
