Rumah > hujung hadapan web > tutorial js > Apakah gelung peristiwa? Penjelasan terperinci tentang gelung acara dalam Node.js

Apakah gelung peristiwa? Penjelasan terperinci tentang gelung acara dalam Node.js

青灯夜游
Lepaskan: 2022-03-25 20:33:26
ke hadapan
1880 orang telah melayarinya

Apakah gelung acara? Artikel ini akan memperkenalkan anda kepada gelung acara dalam Nod Saya harap ia akan membantu anda!

Apakah gelung peristiwa? Penjelasan terperinci tentang gelung acara dalam Node.js

Apakah gelung peristiwa?

Walaupun JavaScript adalah satu-benang, gelung peristiwa menggunakan kernel sistem sebanyak mungkin yang membolehkan Node.js melaksanakan operasi I/O tanpa sekatan Walaupun kebanyakan kernel moden berbilang benang, ia boleh mengendalikan tugas berbilang benang di latar belakang. Apabila tugasan selesai, kernel memberitahu Node.js, dan kemudian panggilan balik yang sesuai akan ditambahkan pada gelung untuk pelaksanaan Artikel ini akan memperkenalkan topik ini dengan lebih terperinci

Gelung masa. penjelasan

Apabila Node.js mula melaksanakan, ia akan mula-mula memulakan gelung peristiwa dan memproses skrip input yang disediakan (atau memasukkannya ke dalam REPL, yang tidak diliputi dalam dokumen ini). akan melaksanakan panggilan API tak segerak dan menjadualkan masa atau proses panggilan.nextTick(), dan kemudian mula memproses gelung acara

Rajah berikut menunjukkan gambaran ringkas bagi urutan pelaksanaan gelung acara

   ┌───────────────────────────┐
┌─>│           timers          │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │     pending callbacks     │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │       idle, prepare       │
│  └─────────────┬─────────────┘      ┌───────────────┐
│  ┌─────────────┴─────────────┐      │   incoming:   │
│  │           poll            │<─────┤  connections, │
│  └─────────────┬─────────────┘      │   data, etc.  │
│  ┌─────────────┴─────────────┐      └───────────────┘
│  │           check           │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
└──┤      close callbacks      │
   └───────────────────────────┘
Salin selepas log masuk
<. 🎜>

Setiap kotak mewakili acara A peringkat gelung

Setiap peringkat mempunyai pelaksanaan panggilan balik baris gilir FIFO Walau bagaimanapun, setiap peringkat dilaksanakan dengan cara tersendiri gelung memasuki peringkat, ia akan Melaksanakan sebarang operasi dalam peringkat semasa dan mula melaksanakan panggilan balik dalam baris gilir peringkat semasa sehingga baris gilir digunakan sepenuhnya atau data maksimum dalam baris gilir dicapai. Apabila baris gilir habis atau mencapai saiz maksimumnya, gelung acara bergerak ke peringkat seterusnya.

Gambaran Keseluruhan Fasa

  • pemasa Fasa ini melaksanakan panggilan balik setTimeout() dan setInterval()< . >poll Dapatkan semula acara I/O baharu; laksanakan panggilan balik berkaitan I/O (hampir semua panggilan balik yang berkaitan, tutup panggilan balik,)
  • semak setImmediate() akan berada di sini Panggilan peringkat
  • tutup panggil balik tutup panggilan balik, contohnya: socket.on('close', ...)
  • dalam setiap proses gelung acara , Nod. js menyemak sama ada ia sedang menunggu I/O tak segerak dan pemasa, jika tidak ia ditutup sepenuhnya
  • Butiran Fasa
  • pemasa

Pemasa menentukan titik kritikal di mana panggilan balik akan dilaksanakan, dan bukannya masa yang dikehendaki untuk dilaksanakan Pemasa akan dilaksanakan seawal mungkin selepas masa berlalu yang ditentukan penjadualan atau panggilan balik lain boleh menangguhkan pelaksanaannya.

Secara teknikalnya, fasa tinjauan pendapat menentukan apabila panggilan balik dilaksanakan Sebagai contoh, anda menetapkan pemasa untuk melaksanakan selepas 100 ms, tetapi skrip anda membaca fail secara tidak segerak. Ia mengambil masa 95ms

Apabila gelung acara memasuki fasa tinjauan pendapat, terdapat baris gilir kosong (fs.readFile() masih belum selesai), jadi ia akan menunggu baki milisaat sehingga masa terpantas Ambang pemproses dicapai. Selepas 95 ms, fs.readFile() melengkapkan membaca fail dan akan mengambil masa 10 ms untuk melengkapkan penambahan pada peringkat tinjauan pendapat dan melengkapkan pelaksanaan Apabila panggilan balik selesai, tiada panggilan balik dalam baris gilir yang akan dilaksanakan dan gelung acara kembali ke peringkat pemasa, laksanakan panggilan balik pemasa. Dalam contoh ini, anda akan melihat bahawa pemasa ditangguhkan selama 105 ms sebelum melaksanakan

Untuk menghalang fasa tinjauan pendapat daripada menyekat gelung acara, libuv (pustaka bahasa C yang melaksanakan gelung acara dan semua kelakuan tak segerak pada platform) Terdapat juga nilai maksimum dalam fasa tinjauan pendapat untuk menghentikan pengundian untuk lebih banyak acara

panggilan balik belum selesai

Fasa ini melaksanakan panggilan balik untuk operasi sistem tertentu (seperti jenis ralat TCP). Contohnya, sesetengah sistem *nix mahu menunggu ralat dilaporkan jika soket TCP menerima ECONNREFUSED apabila cuba menyambung. Ini akan dibariskan untuk pelaksanaan semasa fasa panggil balik yang belum selesai.

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
  }
});
Salin selepas log masuk
pungutan suara

Fasa tinjauan pendapat mempunyai dua fungsi utama

Kira masa menyekat I/O

Acara Pelaksanaan dalam baris gilir tinjauan pendapat

Apabila gelung acara memasuki fasa tinjauan pendapat dan tiada pemasa, dua perkara berikut berlaku

Jika baris gilir tinjauan pendapat tidak kosong, gelung peristiwa Setiap panggil balik akan dilaksanakan secara berulang secara serentak sehingga semua dilaksanakan, atau had keras sistem dicapai

Jika baris gilir tinjauan pendapat kosong, dua situasi berikut akan berlaku
  1. Jika ia adalah setPanggil balik segera, Gelung acara akan menamatkan fasa tinjauan pendapat dan memasuki fasa semakan untuk melaksanakan panggilan balik
  2. Jika ia tidak ditetapkanSegera, gelung acara akan menunggu untuk panggilan balik ditambahkan pada baris gilir, dan kemudian laksanakan ia serta-merta

    Sebaik sahaja baris gilir undian kosong, gelung acara akan mengesan sama ada pemasa telah tamat tempoh, jika ya, gelung acara akan mencapai peringkat pemasa dan melaksanakan pemasa panggil balik
  • 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;);
    });
    Salin selepas log masuk
    $ node timeout_vs_immediate.js
    timeout
    immediate
    
    $ node timeout_vs_immediate.js
    immediate
    timeout
    Salin selepas log masuk

    然而,如果你移动到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;);
      });
    });
    Salin selepas log masuk
    $ node timeout_vs_immediate.js
    immediate
    timeout
    
    $ node timeout_vs_immediate.js
    immediate
    timeout
    Salin selepas log masuk

    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;)
        );
    }
    Salin selepas log masuk

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

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

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

    Atas ialah kandungan terperinci Apakah gelung peristiwa? Penjelasan terperinci tentang gelung acara dalam Node.js. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:juejin.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan