目次
#イベント ループとは何ですか? " >#イベント ループとは何ですか?
#タイム ループ説明" >#タイム ループ説明
フェーズの概要" >フェーズの概要
timer" > timer
タイマーは、コールバックを実行したい時間ではなく、コールバックが実行される重要なポイントを指定します。タイマーは、指定された経過時間が経過した後、できるだけ早く実行されます。オペレーティング システムのスケジューリングやその他のコールバックにより、実行が遅れる可能性があります。
このフェーズでは、特定のシステム操作 (たとえば、 TCP エラーの種類として)。たとえば、一部の *nix システムは、接続しようとしたときに TCP ソケットが ECONNREFUSED を受信した場合、エラーが報告されるのを待ちます。これは、保留中のコールバック フェーズ中に実行するためにキューに入れられます。
ポーリング フェーズには 2 つの主な機能があります
check
close callbacks
setImmediate() VS setTimeout()
process.nextTick()
为什么这会被允许
ホームページ ウェブフロントエンド jsチュートリアル イベントループとは何ですか? Node.jsのイベントループの詳しい説明

イベントループとは何ですか? Node.jsのイベントループの詳しい説明

Mar 25, 2022 pm 08:32 PM
node.js イベントループ

イベントループとは何ですか?この記事では、Node のイベント ループについて紹介します。お役に立てれば幸いです。

イベントループとは何ですか? Node.jsのイベントループの詳しい説明

#イベント ループとは何ですか?

JavaScript はシングルスレッドですが、イベント ループは可能な限りシステム カーネルを使用して、

Node.js がノンブロッキング I/O 操作を実行できるようにします。 最新のカーネルのほとんどはマルチスレッドですが、バックグラウンドでマルチスレッド タスクを処理できます。タスクが完了すると、カーネルは Node.js に通知し、適切なコールバックが実行用のループに追加されます。この記事では、このトピックについてさらに詳しく紹介します

#タイム ループ説明

Node.js が実行を開始すると、まずイベント ループを初期化し、提供された入力スクリプトを処理します (または、それを REPL に入れますが、このドキュメントでは説明しません)。これにより、非同期 API 呼び出しが実行され、タイミングがスケジュールされます。handler、または process.nextTick() を呼び出して、イベント ループの処理を開始します。

次の図は、イベント ループの実行シーケンスの簡略化された概要を示しています

   ┌───────────────────────────┐
┌─>│           timers          │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │     pending callbacks     │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │       idle, prepare       │
│  └─────────────┬─────────────┘      ┌───────────────┐
│  ┌─────────────┴─────────────┐      │   incoming:   │
│  │           poll            │<─────┤  connections, │
│  └─────────────┬─────────────┘      │   data, etc.  │
│  ┌─────────────┴─────────────┐      └───────────────┘
│  │           check           │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
└──┤      close callbacks      │
   └───────────────────────────┘
ログイン後にコピー

各ボックスはイベント ループ ステージを表します

各ステージには FIFO キュー コールバックの実行があります。ただし、各ステージは独自の方法で実行されます。一般的に、イベント ループが実行されると、ステージに入ると、現在の操作が実行されます。ステージ内のすべての操作について、現在のステージのキュー内のコールバックは、キューが完全に消費されるか、キューの最大データに達するまで実行されます。キューが使い果たされるか、最大サイズに達すると、イベント ループは次のステージに移動します。

フェーズの概要

  • timers このステージでは、setTimeout() および setInterval()# のコールバックを実行します。
  • ##pending callbacks
  • 次のループ反復まで I/O コールバックの実行を遅らせます #idle,prepare
  • 内部使用のみ
  • poll
  • 新しい I/O イベントを取得し、I/O 関連のコールバックを実行します (ほぼすべての関連コールバック、クローズ コールバック)
  • check
  • setImmediate() がここにあります フェーズ呼び出し
  • コールバックを閉じる
  • コールバックを閉じる。例:socket.on('close', ...)
  • イベント ループの各プロセスで、Node .js は、非同期 I/O とタイマーを待っているかどうかを確認し、そうでない場合は完全にシャットダウンします

フェーズの詳細

timer

タイマーは、コールバックを実行したい時間ではなく、コールバックが実行される重要なポイントを指定します。タイマーは、指定された経過時間が経過した後、できるだけ早く実行されます。オペレーティング システムのスケジューリングやその他のコールバックにより、実行が遅れる可能性があります。

技術的に言えば、コールバックがいつ実行されるかはポーリング フェーズによって決まります

たとえば、タイマーを 100 ミリ秒後に実行するように設定しましたが、スクリプトはファイルを非同期で読み取ります。95 ミリ秒かかりました。

const fs = require(&#39;fs&#39;);

function someAsyncOperation(callback) {
  // Assume this takes 95ms to complete
  fs.readFile(&#39;/path/to/file&#39;, callback);
}

const timeoutScheduled = Date.now();

setTimeout(() => {
  const delay = Date.now() - timeoutScheduled;

  console.log(`${delay}ms have passed since I was scheduled`);
}, 100);

// do someAsyncOperation which takes 95 ms to complete
someAsyncOperation(() => {
  const startCallback = Date.now();

  // do something that will take 10ms...
  while (Date.now() - startCallback < 10) {
    // do nothing
  }
});
ログイン後にコピー

イベント ループがポーリング フェーズに入ると、空のキューが存在する (fs.readFile() がまだ完了していない)ため、最速のタイマーしきい値に達する (95 ミリ秒後に到達する) まで残りのミリ秒間待機します。 fs.readFile() はファイルの読み取りを完了し、ポーリング フェーズへの追加と実行の完了までに 10 ミリ秒かかります。コールバックが完了すると、キューには実行されるコールバックがなく、イベント ループはタイマーに戻ります。フェーズ:タイマーのコールバックを実行します。この例では、タイマーが 105 ミリ秒遅延されてから実行されることがわかります。

ポーリング フェーズがイベント ループをブロックしないようにするには、libuv (イベント ループとすべての非同期動作を実装する C 言語ライブラリ)ポーリング フェーズには、さらに多くのイベントのポーリングを停止するための最大値もあります。

保留中のコールバック

このフェーズでは、特定のシステム操作 (たとえば、 TCP エラーの種類として)。たとえば、一部の *nix システムは、接続しようとしたときに TCP ソケットが ECONNREFUSED を受信した場合、エラーが報告されるのを待ちます。これは、保留中のコールバック フェーズ中に実行するためにキューに入れられます。

poll

ポーリング フェーズには 2 つの主な機能があります

I/O ブロック時間の計算

    実行イベントポーリング キュー内で
  1. #イベント ループがポーリング フェーズに入り、タイマーがない場合、次の 2 つのことが起こります。

ポーリング キューが空でない場合、イベント ループ 各コールバックは、すべてが実行されるか、システムのハード リミットに達するまで、同期して反復的に実行されます。

    ポーリング キューが空の場合、次の 2 つの状況が発生します。
  • setImmediate コールバック。イベント ループはポーリング フェーズを終了し、チェック フェーズに入りコールバックを実行します。
    • setImmediate でない場合、イベント ループはコールバックがキューに追加されるのを待ちます。すぐに実行してください
    ポーリング キューが空になると、イベント ループはタイマーが期限切れかどうかを検出します。期限切れの場合、イベント ループはタイマー ステージに到達して、タイマーコールバック
  • check

    此阶段允许人们在 poll 阶段完成后立即执行回调。 如果轮询阶段变得空闲并且脚本已使用 setImmediate() 排队,则事件循环可能会继续到 check 阶段而不是等待。

    setImmediate() 实际上是一个特殊的计时器,它在事件循环的单独阶段运行。 它使用一个 libuv API 来安排在 poll 阶段完成后执行的回调。

    通常,随着代码的执行,事件循环最终会到达 poll 阶段,它将等待传入的连接、请求等。但是,如果使用 setImmediate() 安排了回调并且 poll 阶段变得空闲,它将结束并继续 check 阶段,而不是等待 poll 事件。

    close callbacks

    如果一个 socket 或者操作突然被关闭(e.g socket.destroy()),close 事件会被发送到这个阶段,否则会通过process.nextTick()发送

    setImmediate() VS setTimeout()

    setImmediate() 和 setTimeout() 是相似的,但是不同的行为取决于在什么时候被调用

    • setTimmediate() 在 poll 阶段一旦执行完就会执行
    • setTimeout() 在一小段时间过去之后被执行

    每个回调执行的顺序依赖他们被调用的上下本环境,如果在同一个模块被同时调用,那么时间会受到进程性能的限制(这也会被运行在这台机器的其他应用所影响)

    例如,如果我们不在I/O里边运行下面的脚本,尽管它受进程性能的影响,但是不能够确定这两个计时器的执行顺序:

    // timeout_vs_immediate.js
    setTimeout(() => {
      console.log(&#39;timeout&#39;);
    }, 0);
    
    setImmediate(() => {
      console.log(&#39;immediate&#39;);
    });
    ログイン後にコピー
    $ node timeout_vs_immediate.js
    timeout
    immediate
    
    $ node timeout_vs_immediate.js
    immediate
    timeout
    ログイン後にコピー

    然而,如果你移动到I/O 循环中,immediate 回调总是会先执行

    // timeout_vs_immediate.js
    const fs = require(&#39;fs&#39;);
    
    fs.readFile(__filename, () => {
      setTimeout(() => {
        console.log(&#39;timeout&#39;);
      }, 0);
      setImmediate(() => {
        console.log(&#39;immediate&#39;);
      });
    });
    ログイン後にコピー
    $ node timeout_vs_immediate.js
    immediate
    timeout
    
    $ node timeout_vs_immediate.js
    immediate
    timeout
    ログイン後にコピー

    setImmediate 相对于 setTimeout 的优势是 setImmediate 如果在I/O 中总是会优先于任何计时器被先执行,与存在多少计时器无关。

    process.nextTick()

    尽管 process.nextTick() 是异步API的一部分,但是你可能已经注意到了它没有出现在图表中,这是因为 process.nextTick() 不是事件循环技术的一部分,相反,当前操作执行完毕之后 nextTickQueue 会被执行,无论事件循环的当前阶段如何。 在这里,操作被定义为来自底层 C/C++ 处理程序的转换,并处理需要执行的 JavaScript。 根据图表,你可以在任意阶段调用 process.nextTick(),在事件循环继续执行之前,所有传递给 process.nextTick() 的回调都将被执行,这个会导致一些坏的情况因为它允许你递归调用 process.nextTick() "starve" 你的 I/O ,这会阻止事件循环进入 poll 阶段。

    为什么这会被允许

    为什么这种情况会被包含在Node.js中?因为Node.js的设计理念是一个API应该总是异步的即使它不必须,看看下面的片段

    function apiCall(arg, callback) {
      if (typeof arg !== &#39;string&#39;)
        return process.nextTick(
          callback,
          new TypeError(&#39;argument should be string&#39;)
        );
    }
    ログイン後にコピー

    该片段会进行参数检查,如果不正确,它会将错误传递给回调。 API 最近更新,允许将参数传递给 process.nextTick() 允许它接受在回调之后传递的任何参数作为回调的参数传播,因此您不必嵌套函数。

    我们正在做的是将错误传回给用户,但前提是我们允许用户的其余代码执行。 通过使用 process.nextTick(),我们保证 apiCall() 总是在用户代码的其余部分之后和允许事件循环继续之前运行它的回调。 为了实现这一点,允许 JS 调用堆栈展开,然后立即执行提供的回调,这允许人们对 process.nextTick() 进行递归调用,而不会达到 RangeError:从 v8 开始超出最大调用堆栈大小。

    更多node相关知识,请访问:nodejs 教程

    以上がイベントループとは何ですか? Node.jsのイベントループの詳しい説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

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

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

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

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

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

Node V8 エンジンのメモリと GC の詳細な図による説明 Node V8 エンジンのメモリと GC の詳細な図による説明 Mar 29, 2023 pm 06:02 PM

この記事では、NodeJS V8 エンジンのメモリとガベージ コレクター (GC) について詳しく説明します。

Nodeのメモリ制御に関する記事 Nodeのメモリ制御に関する記事 Apr 26, 2023 pm 05:37 PM

ノンブロッキングおよびイベント駆動に基づいて構築されたノード サービスには、メモリ消費量が少ないという利点があり、大量のネットワーク リクエストの処理に非常に適しています。大量のリクエストを前提として、「メモリ制御」に関する問題を考慮する必要があります。 1. V8 のガベージ コレクション メカニズムとメモリ制限 Js はガベージ コレクション マシンによって制御されます

最適な Node.js Docker イメージを選択する方法について話しましょう。 最適な Node.js Docker イメージを選択する方法について話しましょう。 Dec 13, 2022 pm 08:00 PM

ノード用の Docker イメージの選択は些細なことのように思えるかもしれませんが、イメージのサイズと潜在的な脆弱性は、CI/CD プロセスとセキュリティに大きな影響を与える可能性があります。では、最適な Node.js Docker イメージを選択するにはどうすればよいでしょうか?

Node.js 19 が正式リリースされました。その 6 つの主要な機能についてお話しましょう。 Node.js 19 が正式リリースされました。その 6 つの主要な機能についてお話しましょう。 Nov 16, 2022 pm 08:34 PM

Node 19 が正式リリースされましたので、この記事では Node.js 19 の 6 つの主要な機能について詳しく説明します。

Node の File モジュールについて詳しく説明しましょう Node の File モジュールについて詳しく説明しましょう Apr 24, 2023 pm 05:49 PM

ファイル モジュールは、ファイルの読み取り/書き込み/開く/閉じる/削除の追加など、基礎となるファイル操作をカプセル化したものです。ファイル モジュールの最大の特徴は、すべてのメソッドが **同期** と ** の 2 つのバージョンを提供することです。 asynchronous**、sync サフィックスが付いているメソッドはすべて同期メソッドであり、持たないメソッドはすべて異種メソッドです。

Nodeのイベントループについて話しましょう Nodeのイベントループについて話しましょう Apr 11, 2023 pm 07:08 PM

イベント ループは Node.js の基本的な部分であり、メイン スレッドがブロックされていないことを確認することで非同期プログラミングが可能になります。イベント ループを理解することは、効率的なアプリケーションを構築するために重要です。次の記事では、Node のイベント ループについて詳しく説明します。お役に立てれば幸いです。

pkg を使用して Node.js プロジェクトを実行可能ファイルにパッケージ化する方法について説明します。 pkg を使用して Node.js プロジェクトを実行可能ファイルにパッケージ化する方法について説明します。 Dec 02, 2022 pm 09:06 PM

Nodejs実行可能ファイルをpkgでパッケージ化するにはどうすればよいですか?次の記事では、pkg を使用して Node プロジェクトを実行可能ファイルにパッケージ化する方法を紹介します。

Node.js の GC (ガベージ コレクション) メカニズムについて話しましょう Node.js の GC (ガベージ コレクション) メカニズムについて話しましょう Nov 29, 2022 pm 08:44 PM

Node.js はどのように GC (ガベージ コレクション) を行うのでしょうか?次の記事で詳しく説明します。

See all articles