亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

Node.js Event Loop之Timers, process.nextTick()

sarva / 1186人閱讀

摘要:前言以異步和事件驅(qū)動(dòng)的特性著稱但異步是怎么實(shí)現(xiàn)的呢其中核心的一部分就是下文中內(nèi)容基本來自于文檔有不準(zhǔn)確地方請(qǐng)指出什么是能讓的操作表現(xiàn)得無阻塞盡管是單線程的但通過盡可能的將操作放到操作系統(tǒng)內(nèi)核由于現(xiàn)在大多數(shù)內(nèi)核都是多線程的它們可以在后臺(tái)執(zhí)行多

前言

Node.js以異步I/O和事件驅(qū)動(dòng)的特性著稱,但異步I/O是怎么實(shí)現(xiàn)的呢?其中核心的一部分就是event loop,下文中內(nèi)容基本來自于Node.js文檔,有不準(zhǔn)確地方請(qǐng)指出.

什么是Event loop

event loop能讓Node.js的I/O操作表現(xiàn)得無阻塞,盡管JavaScript是單線程的但通過盡可能的將操作放到操作系統(tǒng)內(nèi)核.

由于現(xiàn)在大多數(shù)內(nèi)核都是多線程的,它們可以在后臺(tái)執(zhí)行多個(gè)操作. 當(dāng)這些操作完成時(shí),內(nèi)核通知Node.js應(yīng)該把回調(diào)函數(shù)添加到poll隊(duì)列被執(zhí)行.我們將在接下來的話題里詳細(xì)討論.

Event Loop 說明

當(dāng)Node.js開始時(shí),它將會(huì)初始化event loop,處理提供可能造成異步API調(diào)用,timers任務(wù),或調(diào)用process.nextTick()的腳本(或者將它放到[REPL][]中,這篇文章中將不會(huì)討論),然后開始處理event loop.

下面是一張event loop操作的簡單概覽圖.

   ┌───────────────────────┐
┌─>│        timers         │
│  └──────────┬────────────┘
│  ┌──────────┴────────────┐
│  │     I/O callbacks     │
│  └──────────┬────────────┘
│  ┌──────────┴────────────┐
│  │     idle, prepare     │
│  └──────────┬────────────┘      ┌───────────────┐
│  ┌──────────┴────────────┐      │   incoming:   │
│  │         poll          │<─────┤  connections, │
│  └──────────┬────────────┘      │   data, etc.  │
│  ┌──────────┴────────────┐      └───────────────┘
│  │        check          │
│  └──────────┬────────────┘
│  ┌──────────┴────────────┐
└──┤    close callbacks    │
   └───────────────────────┘

注意: 每一個(gè)方框?qū)⒈缓喎Q為一個(gè)event loop的階段.

每一個(gè)階段都有一個(gè)回調(diào)函數(shù)的FIFO隊(duì)列被執(zhí)行.每一個(gè)階段都有自己特有的方式,通常even loop進(jìn)入一個(gè)給定的階段時(shí),它將執(zhí)行該階段任何的特定操作,然后執(zhí)行該階段隊(duì)列中的回調(diào)函數(shù),直到執(zhí)行完所有回調(diào)或執(zhí)行了最大回調(diào)的次數(shù).當(dāng)隊(duì)列中的回調(diào)已被執(zhí)行完或者到達(dá)了限制次數(shù),eventloop將會(huì)從下一個(gè)階段開始依次執(zhí)行.

由于這些操作可能造成更多的操作,并且在poll階段中產(chǎn)生的新事件被內(nèi)核推入隊(duì)列,所以poll事件可以被推入隊(duì)列當(dāng)有其它poll事件正在執(zhí)行時(shí).因此長時(shí)間執(zhí)行回調(diào)可以允許poll階段超過timers設(shè)定的時(shí)間.詳細(xì)內(nèi)容請(qǐng)看timerspoll章節(jié).

ps: 個(gè)人理解-在輪詢階段一個(gè)回調(diào)執(zhí)行可能會(huì)產(chǎn)生新的事件處理,這些新事件會(huì)被推入到輪詢隊(duì)列中,所以poll階段可以一直執(zhí)行回調(diào),即使timers的回調(diào)已到時(shí)間應(yīng)該被執(zhí)行時(shí).

注意: Windows和Unix/Linux在實(shí)現(xiàn)時(shí)有一些細(xì)微的差異,但那都不是事兒.重點(diǎn)是: 實(shí)際上有7或8個(gè)步驟,Node.js實(shí)際上使用的是它們所有.

階段概覽

timers: 這個(gè)階段執(zhí)行setTimeout()setInterval()產(chǎn)生的回調(diào).

I/O callbacks: 執(zhí)行大多數(shù)的回調(diào),除了close callbacks,timers和setImmediate()的回調(diào).

idle, prepare: 僅供內(nèi)部使用.

poll: 獲取新的I/O事件;node會(huì)在適當(dāng)時(shí)候在這里阻塞.

check: 執(zhí)行setImmediate()回調(diào).

close callbacks: e.g. socket.on("close", ...).

在每次event loop之間,Node.js會(huì)檢查它是否正在等待任何異步I/O或計(jì)時(shí)器,如果沒有就會(huì)完全關(guān)閉.

階段詳情 timers

一個(gè)定時(shí)器指定的是執(zhí)行回調(diào)函數(shù)的閾值,而不是確定的時(shí)間點(diǎn).定時(shí)器的回調(diào)將在規(guī)定的時(shí)間過后運(yùn)行;然而,操作系統(tǒng)調(diào)度或其他回調(diào)函數(shù)的運(yùn)行可能會(huì)使執(zhí)行回調(diào)延遲.

注意: 技術(shù)上,poll 階段控制了timers被執(zhí)行.

例如, 你要在100ms的延時(shí)后在回調(diào)函數(shù)并且執(zhí)行一個(gè)耗時(shí)95ms的異步讀取文本操作:

const fs = require("fs");

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

const timeoutScheduled = Date.now();

setTimeout(function() {

  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(function() {

  const startCallback = Date.now();

  // do something that will take 10ms...
  while (Date.now() - startCallback < 10) {
    // do nothing
  }

});

// 輸出: 105ms have passed since I was scheduled

當(dāng)event loop進(jìn)入poll階段時(shí),它是一個(gè)空的隊(duì)列(fs.readFile()還沒有完成),所以它會(huì)等待數(shù)毫秒等待timers設(shè)定時(shí)間的到達(dá).直到等待95 ms過后, fs.readFile()完成文件讀取然后它的回調(diào)函數(shù)會(huì)被添加至poll隊(duì)列然后執(zhí)行.當(dāng)執(zhí)行完成后隊(duì)列中沒有其他回調(diào),所以event loop會(huì)查看定時(shí)器設(shè)定的時(shí)間已經(jīng)到達(dá)然后回撤到timers階段執(zhí)行timers的回調(diào)函數(shù).在例子里你會(huì)發(fā)現(xiàn),從定時(shí)器被記錄到執(zhí)行回調(diào)函數(shù)耗時(shí)105ms.

注意: 為了防止poll階段阻塞死event loop, [libuv]
(http://libuv.org/) (實(shí)現(xiàn)Node.js事件循環(huán)的C庫和平臺(tái)的所有異步行為)
也有一個(gè)固定最大值(系統(tǒng)依賴).

I/O callbacks

這個(gè)階段執(zhí)行一些系統(tǒng)操作的回調(diào),例如TCP錯(cuò)誤等類型.例如TCP socket 嘗試連接時(shí)收到了ECONNREFUSED,一些*nix系統(tǒng)想等待錯(cuò)誤日志記錄.這些都將在I/O callbacks階段被推入隊(duì)列執(zhí)行.

poll

poll 階段有兩個(gè)主要的功能:

為已經(jīng)到達(dá)或超時(shí)的定時(shí)器執(zhí)行腳本

處理在poll隊(duì)列中的事件.

當(dāng)event loop進(jìn)入poll階段并且沒有timers任務(wù)時(shí)會(huì)執(zhí)行下面某一條操作:

如果poll隊(duì)列不為空,則event loop會(huì)同步的執(zhí)行回調(diào)隊(duì)列,直到執(zhí)行完回調(diào)或達(dá)到系統(tǒng)最大限制.

如果poll隊(duì)列為空,會(huì)執(zhí)行下面某一條操做:

如果腳本被setImmediate()執(zhí)行,則event loop會(huì)結(jié)束 poll階段,繼續(xù)向下進(jìn)入到check階段執(zhí)行setImmediate()的腳本.

如果腳本不是被setImmediate()執(zhí)行,event loop會(huì)等待回調(diào)函數(shù)被添加至隊(duì)列,然后立刻執(zhí)行它們.

一旦poll隊(duì)列空了,event loop會(huì)檢查timers是否有以滿足條件的定時(shí)器,如果有一個(gè)以上滿足執(zhí)行條件的定時(shí)器,event loop將會(huì)撤回至timers階段去執(zhí)行定時(shí)器的回調(diào)函數(shù).

check

這個(gè)階段允許立刻執(zhí)行一個(gè)回調(diào)在poll階段完成后.如果poll階段已經(jīng)執(zhí)行完成或腳本已經(jīng)使用setImmediate(),event loop 可能就會(huì)繼續(xù)到check階段而不是等待.

setImmediate()實(shí)際是在event loop 獨(dú)立階段運(yùn)行的特殊定時(shí)器.它使用了libuv API來使回調(diào)函數(shù)在poll階段后執(zhí)行.

通常在代碼執(zhí)行時(shí),event loop 最終會(huì)到達(dá)poll階段,等待傳入連接,請(qǐng)求等等.然而,如果有一個(gè)被setImmediate()執(zhí)行的回調(diào),poll階段會(huì)變得空閑,它將會(huì)結(jié)束并進(jìn)入check階段而不是等待新的poll事件.

close callbacks

如果一個(gè)socket或者操作被突然關(guān)閉(例如.socket.destroy()),這個(gè)close事件將在這個(gè)階段被觸發(fā).否則它將會(huì)通過process.nextTick()被觸發(fā).

setImmediate() vs setTimeout()

setImmediatesetTimeout() 是很相似的,但是它們的調(diào)用方式不同導(dǎo)致了會(huì)有不同的表現(xiàn).

setImmediate() 會(huì)中斷poll階段,立即執(zhí)行..

setTimeout() 將在給定的毫秒后執(zhí)行設(shè)定的腳本.

timers的執(zhí)行順序會(huì)根據(jù)它們被調(diào)用的上下文而變化.如果兩個(gè)都在主模塊內(nèi)被調(diào)用,則時(shí)序?qū)⑹艿竭M(jìn)程的性能的限制(可能受機(jī)器上運(yùn)行的其他應(yīng)用程序的影響).

例如,我們執(zhí)行下面兩個(gè)不在I/O周期內(nèi)(主模塊)的腳本,這兩個(gè)timers的執(zhí)行順序是不確定的,它受到進(jìn)程性能的影響:

// timeout_vs_immediate.js
setTimeout(function timeout() {
  console.log("timeout");
}, 0);

setImmediate(function immediate() {
  console.log("immediate");
});
$ node timeout_vs_immediate.js
timeout
immediate

$ node timeout_vs_immediate.js
immediate
timeout

然而,如果你把這兩個(gè)調(diào)用放到I/O周期內(nèi),則immediate的回調(diào)總會(huì)被先執(zhí)行:

// timeout_vs_immediate.js
const fs = require("fs");

fs.readFile(__filename, () => {
  setTimeout(() => {
    console.log("timeout");
  }, 0);
  setImmediate(() => {
    console.log("immediate");
  });
});
$ node timeout_vs_immediate.js
immediate
timeout

$ node timeout_vs_immediate.js
immediate
timeout

使用setImmediate()setTimeout()的好處是setImmediate()在I/O周期內(nèi)總是比所有timers先執(zhí)行,無論有多少timers存在.

process.nextTick() 理解 process.nextTick()

你可能已經(jīng)注意到process.nextTick()沒有在概覽圖中列出,盡管他是異步API的一部分.這是因?yàn)?b>process.nextTick()在技術(shù)上不是event loop的一部分.反而nextTickQueue會(huì)在當(dāng)前操作完成后會(huì)被執(zhí)行,無論當(dāng)前處于event loop的什么階段.

再看看概覽圖,在給定的階段你任何時(shí)候調(diào)用process.nextTick(),通過process.nextTick()指定的回調(diào)函數(shù)都會(huì)在event loop繼續(xù)執(zhí)行前被解析.這可能會(huì)造成一些不好的情況,因?yàn)?strong>它允許你通過遞歸調(diào)用process.nextTick()而造成I/O阻塞死,因?yàn)樗柚沽薳vent loop到達(dá)poll階段.

為什么這種操作會(huì)被允許呢?

部分原因是一個(gè)API應(yīng)該是異步事件盡管它可能不是異步的.看看下面代碼片段:

function apiCall(arg, callback) {
  if (typeof arg !== "string")
    return process.nextTick(callback,
                            new TypeError("argument should be string"));
}

代碼里對(duì)參數(shù)做了校驗(yàn),如果不正確,它將會(huì)在回調(diào)函數(shù)中拋出錯(cuò)誤.API最近更新,允許傳遞參數(shù)給 process.nextTick() ,process.nextTick()可以接受任何參數(shù),回調(diào)函數(shù)被當(dāng)做參數(shù)傳遞給回調(diào)函數(shù)后,你就不必使用嵌套函數(shù)了.

我們所做的就是將錯(cuò)誤回傳給用戶當(dāng)用戶的其它代碼執(zhí)行后.通過使用process.nextTick()我們確保apiCall()執(zhí)行回調(diào)函數(shù)在用戶的代碼之后,在event loop運(yùn)行的階段之前.為了實(shí)現(xiàn)這一點(diǎn),JS調(diào)用的堆棧被允許釋放掉,然后立刻執(zhí)行提供的回調(diào)函數(shù),回調(diào)允許用戶遞歸的調(diào)用process.nextTick()直到v8限制的調(diào)用堆棧最大值.

這種理念可能會(huì)導(dǎo)致一些潛在的問題.來看這段代碼:

let bar;

// this has an asynchronous signature, but calls callback synchronously
function someAsyncApiCall(callback) { callback(); }

// the callback is called before `someAsyncApiCall` completes.
someAsyncApiCall(() => {

  // since someAsyncApiCall has completed, bar hasn"t been assigned any value
  console.log("bar", bar); // undefined

});

bar = 1;

用戶定義了一個(gè)有異步標(biāo)簽的函數(shù)someAsyncApiCall(),盡管他的操作是同步的.當(dāng)它被調(diào)用的時(shí)候,提供的回調(diào)函數(shù)在event loop的同一階段中被調(diào)用,因?yàn)?b>someAsyncApiCall()沒有任何異步操作.所以回調(diào)函數(shù)嘗試引用bar盡管這個(gè)變量在作用域沒有值,因?yàn)榇a還沒有執(zhí)行到最后.

通過將回調(diào)函數(shù)放在process.nextTick()里,代碼仍然有執(zhí)行完的能力,允許所有的變量,函數(shù)等先被初始化來供回調(diào)函數(shù)調(diào)用.它還有不允許event loop繼續(xù)執(zhí)行的優(yōu)勢.它可能在event loop繼續(xù)執(zhí)行前拋出一個(gè)錯(cuò)誤給用戶很有用.這里提供一個(gè)使用process.nextTick()的示例:

let bar;

function someAsyncApiCall(callback) {
  process.nextTick(callback);
}

someAsyncApiCall(() => {
  console.log("bar", bar); // 1
});

bar = 1;

這里有另一個(gè)真實(shí)的例子:

const server = net.createServer(() => {}).listen(8080);

server.on("listening", () => {});

僅當(dāng)端口可用時(shí)端口立即被綁定.所以"listening"的回調(diào)函數(shù)能立即被調(diào)用.問題是那時(shí)候不會(huì)設(shè)置.on("listening").

為了解決這個(gè)問題,"listening"事件被放入nextTick()隊(duì)列來允許代碼執(zhí)行完.這會(huì)允許用戶設(shè)置他們想要的任何事件處理.

process.nextTick() vs setImmediate()

我們有兩個(gè)直到現(xiàn)在用戶都關(guān)心的相似的調(diào)用,但他們的名字令人困惑.

process.nextTick() 在同一階段立即觸發(fā)

setImmediate() 在以下迭代器或者event loop的"tick"中觸發(fā)

本質(zhì)上,這兩個(gè)名字應(yīng)該交換.process.nextTick()setImmediate()觸發(fā)要快但這是一個(gè)不想改變的歷史的命名.做這個(gè)改變會(huì)破壞npm上大多數(shù)包.每天都有新模塊被增加,意味著每天我們都在等待更多的潛在錯(cuò)誤發(fā)生.當(dāng)他們困惑時(shí),這個(gè)名字就不會(huì)被改變.

我們建議開發(fā)者使用setImmediate()因?yàn)樗菀妆焕斫?并且它保持了更好的兼容性,例如瀏覽器的JS)

為什么使用process.nextTick()?

有兩個(gè)主要原因:

允許用戶處理錯(cuò)誤,清除任何不需要的資源,或者可能在事件循環(huán)繼續(xù)之前再次嘗試該請(qǐng)求.

同時(shí)有必要允許回調(diào)函數(shù)執(zhí)行在調(diào)用堆棧釋放之后但在event loop繼續(xù)之前.

一個(gè)滿足用戶期待的簡單例子:

const server = net.createServer();
server.on("connection", function(conn) { });

server.listen(8080);
server.on("listening", function() { });

listen()在event loop開始時(shí)執(zhí)行,但是listening的回調(diào)函數(shù)被放在一個(gè)setImmediate()中.現(xiàn)在除非主機(jī)名可用于綁定端口會(huì)立即執(zhí)行.現(xiàn)在為了event loop繼續(xù)執(zhí)行,它必須進(jìn)入poll階段,意味著在監(jiān)聽事件前且沒有觸發(fā)允許連接事件時(shí)沒有接收到請(qǐng)求的可能.

另一個(gè)例子是運(yùn)行一個(gè)函數(shù)構(gòu)造函數(shù),例如,繼承自EventEmitter,并且想要在構(gòu)造函數(shù)中調(diào)用一個(gè)事件:

const EventEmitter = require("events");
const util = require("util");

function MyEmitter() {
  EventEmitter.call(this);
  this.emit("event");
}
util.inherits(MyEmitter, EventEmitter);

const myEmitter = new MyEmitter();
myEmitter.on("event", function() {
  console.log("an event occurred!");
});

你不能在構(gòu)造函數(shù)中立即觸發(fā)事件,因?yàn)榇a不會(huì)執(zhí)行到用戶為該事件分配回調(diào)函數(shù)的地方,所以,在構(gòu)造函數(shù)本身中,你可以使用process.nextTick()設(shè)置回調(diào)函數(shù)來在夠咱函數(shù)完成后觸發(fā)事件.有一個(gè)小栗子:

const EventEmitter = require("events");
const util = require("util");

function MyEmitter() {
  EventEmitter.call(this);

  // use nextTick to emit the event once a handler is assigned
  process.nextTick(function() {
    this.emit("event");
  }.bind(this));
}
util.inherits(MyEmitter, EventEmitter);

const myEmitter = new MyEmitter();
myEmitter.on("event", function() {
  console.log("an event occurred!");
});
部分個(gè)人理解

前面基本是基于文檔的翻譯(由于英文能力問題,很多地方都模模糊糊,甚至是狗屁不通[捂臉]),下面寫一些重點(diǎn)部分的理解

幾個(gè)概念

event loop是跑在主進(jìn)程上的一個(gè)while(true) {}循環(huán).

timers階段包括setTimeout(),setInterval()兩個(gè)定時(shí)器,回調(diào)執(zhí)行時(shí)間等于或者晚于定時(shí)器設(shè)定的時(shí)間,因?yàn)樵?strong>poll階段會(huì)執(zhí)行其它回調(diào)函數(shù),在空閑時(shí)才回去檢查定時(shí)器(event loop的開始和結(jié)束時(shí)檢查).

在I/O callback階段,雖然在階段介紹里說的是執(zhí)行除timers,Immediate,close之外的所有回調(diào),但后面詳細(xì)介紹中又說了,這里執(zhí)行的大多是stream, pipe, tcp, udp通信錯(cuò)誤的回調(diào),例如fs產(chǎn)生的回調(diào)應(yīng)該還是在poll階段執(zhí)行的.

poll階段應(yīng)該才是真正的執(zhí)行了除timers,Immediate,close外的所有回調(diào).

process.nextTick()沒有在任何一個(gè)階段執(zhí)行,它執(zhí)行的時(shí)間應(yīng)該是在各個(gè)階段切換的中間執(zhí)行.

幾段代碼
const fs = require("fs");

fs.readFile("../mine.js", () => {
    setTimeout(() => { console.log("setTimeout") }, 0);
    process.nextTick(() => { console.log("process.nextTick") })
    setImmediate(() => { console.log("setImmediate") })
});
/*log -------------------
process.nextTick
setImmediate
setTimeout
*/

當(dāng)文件讀取完成后在poll階段執(zhí)行回調(diào)函數(shù)

setTimeout添加至timers隊(duì)列,解析process.nextTick()回調(diào)函數(shù),將setImmediate添加至check隊(duì)列

poll隊(duì)列為空,有setImmediate的代碼,繼續(xù)向下一個(gè)階段.

在到達(dá)check階段前執(zhí)行process.nextTick()回調(diào)函數(shù)

check階段執(zhí)行setImmediate

timers階段執(zhí)行setTimeout回調(diào)

const fs = require("fs");

const start = new Date();
fs.readFile("../mine.js", () => {
    setTimeout(() => { console.log("setTimeout spend: ", new Date() - start) }, 0);
    setImmediate(() => { console.log("setImmediate spend: ", new Date() - start) })
    process.nextTick(() => { console.log("process.nextTick spend: ", new Date() - start) })
});
setTimeout(() => { console.log("setTimeout-main spend: ", new Date() - start) }, 0);
setImmediate(() => { console.log("setImmediate-main spend: ", new Date() - start) })
process.nextTick(() => { console.log("process.nextTick-main spend: ", new Date() - start) })
/* log ----------------
process.nextTick-main spend:  9
setTimeout-main spend:  12
setImmediate-main spend:  13
process.nextTick spend:  14
setImmediate spend:  15
setTimeout spend:  15
*/

這里沒有搞懂為什么主進(jìn)程內(nèi)的setTimeout總是比setImmediate先執(zhí)行,按文檔所說,兩個(gè)應(yīng)該是不確定誰先執(zhí)行.

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/84886.html

相關(guān)文章

  • Node.js】理解事件循環(huán)機(jī)制

    摘要:前沿是基于引擎的運(yùn)行環(huán)境具有事件驅(qū)動(dòng)非阻塞等特點(diǎn)結(jié)合具有網(wǎng)絡(luò)編程文件系統(tǒng)等服務(wù)端的功能用庫進(jìn)行異步事件處理線程的單線程含義實(shí)際上說的是執(zhí)行同步代碼的主線程一個(gè)程序的啟動(dòng)不止是分配了一個(gè)線程,而是我們只能在一個(gè)線程執(zhí)行代碼當(dāng)出現(xiàn)資源調(diào)用連接等 前沿 Node.js 是基于V8引擎的javascript運(yùn)行環(huán)境. Node.js具有事件驅(qū)動(dòng), 非阻塞I/O等特點(diǎn). 結(jié)合Node API, ...

    Riddler 評(píng)論0 收藏0
  • JS異步詳解 - 瀏覽器/Node/事件循環(huán)/消息隊(duì)列/宏任務(wù)/微任務(wù)

    js異步歷史 一個(gè) JavaScript 引擎會(huì)常駐于內(nèi)存中,它等待著我們把JavaScript 代碼或者函數(shù)傳遞給它執(zhí)行 在 ES3 和更早的版本中,JavaScript 本身還沒有異步執(zhí)行代碼的能力,引擎就把代碼直接順次執(zhí)行了,異步任務(wù)都是宿主環(huán)境(瀏覽器)發(fā)起的(setTimeout、AJAX等)。 在 ES5 之后,JavaScript 引入了 Promise,這樣,不需要瀏覽器的安排,J...

    awesome23 評(píng)論0 收藏0
  • Node中的事件循環(huán)和異步API

    摘要:異步在中,是在單線程中執(zhí)行的沒錯(cuò),但是內(nèi)部完成工作的另有線程池,使用一個(gè)主進(jìn)程和多個(gè)線程來模擬異步。在事件循環(huán)中,觀察者會(huì)不斷的找到線程池中已經(jīng)完成的請(qǐng)求對(duì)象,從中取出回調(diào)函數(shù)和數(shù)據(jù)并執(zhí)行。 1. 介紹 單線程編程會(huì)因阻塞I/O導(dǎo)致硬件資源得不到更優(yōu)的使用。多線程編程也因?yàn)榫幊讨械乃梨i、狀態(tài)同步等問題讓開發(fā)人員頭痛。Node在兩者之間給出了它的解決方案:利用單線程,遠(yuǎn)離多線程死鎖、狀態(tài)...

    atinosun 評(píng)論0 收藏0
  • FE.ES-理解Event Loop

    摘要:新加了一個(gè)微任務(wù)和一個(gè)宏任務(wù)在當(dāng)前執(zhí)行棧的尾部下一次之前觸發(fā)回調(diào)函數(shù)。階段這個(gè)階段主要執(zhí)行一些系統(tǒng)操作帶來的回調(diào)函數(shù),如錯(cuò)誤,如果嘗試鏈接時(shí)出現(xiàn)錯(cuò)誤,一些會(huì)把這個(gè)錯(cuò)誤報(bào)告給。 JavaScript引擎又稱為JavaScript解釋器,是JavaScript解釋為機(jī)器碼的工具,分別運(yùn)行在瀏覽器和Node中。而根據(jù)上下文的不同,Event loop也有不同的實(shí)現(xiàn):其中Node使用了libu...

    longshengwang 評(píng)論0 收藏0
  • 做面試的不倒翁:一道事件循環(huán)題引發(fā)的血案

    摘要:通過查看的文檔可以發(fā)現(xiàn)整個(gè)分為個(gè)階段定時(shí)器相關(guān)任務(wù),中我們關(guān)注的是它會(huì)執(zhí)行和中到期的回調(diào)執(zhí)行某些系統(tǒng)操作的回調(diào)內(nèi)部使用執(zhí)行,一定條件下會(huì)在這個(gè)階段阻塞住執(zhí)行的回調(diào)如果或者關(guān)閉了,就會(huì)在這個(gè)階段觸發(fā)事件,執(zhí)行事件的回調(diào)的代碼在文件中。 showImg(https://segmentfault.com/img/bVbd7B7?w=1227&h=644); 這次我們就不要那么多前戲,直奔主題...

    ispring 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

sarva

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<