成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Node.js中的事件循環(huán)(Event Loop),計(jì)時(shí)器(Timers)以及process.nex

KoreyLee / 1286人閱讀

摘要:回調(diào)函數(shù)執(zhí)行幾乎所有的回調(diào)函數(shù),除了關(guān)閉回調(diào)函數(shù),定時(shí)器計(jì)劃的回調(diào)函數(shù)和。輪詢此階段有兩個(gè)主要的功能執(zhí)行已過(guò)時(shí)的定時(shí)器腳本處理輪詢隊(duì)列中的事件。一旦輪詢隊(duì)列為空,事件循環(huán)將檢查已達(dá)到時(shí)間閾值的定時(shí)器。

什么是事件循環(huán)(Event Loop)?

事件環(huán)使得Node.js可以執(zhí)行非阻塞I/O 操作,只要有可能就將操作卸載到系統(tǒng)內(nèi)核,盡管JavaScript是單線程的。

由于大多數(shù)現(xiàn)代(終端)內(nèi)核都是多線程的,他們可以處理在后臺(tái)執(zhí)行的多個(gè)操作。 當(dāng)其中一個(gè)操作完成時(shí),內(nèi)核會(huì)通知Node.js,以便可以將適當(dāng)?shù)幕卣{(diào)添加到輪詢隊(duì)列poll queue中以最終執(zhí)行。 我們將在本主題后面進(jìn)一步詳細(xì)解釋這一點(diǎn)。

事件循環(huán):解釋

當(dāng)Node.js開(kāi)始運(yùn)行,它初始化事件環(huán)、處理提供的輸入腳本(或放入REPL,本文檔未涉及),這可能會(huì)使異步API調(diào)用,計(jì)劃定時(shí)器或調(diào)用process.nextTick(),然后開(kāi)始處理事件循環(huán)。

下圖顯示了事件循環(huán)的操作順序的簡(jiǎn)化概述。

   ┌───────────────────────┐
┌─>│    timers(計(jì)時(shí)器)    │
│  └──────────┬────────────┘
│  ┌──────────┴────────────┐
│  │     I/O callbacks     │
│  └──────────┬────────────┘
│  ┌──────────┴────────────┐
│  │   idle, prepare 內(nèi)部  │
│  └──────────┬────────────┘      ┌───────────────┐
│  ┌──────────┴────────────┐      │   incoming:   │
│  │      poll(輪詢)      │<─────┤  connections, │
│  └──────────┬────────────┘      │   data, etc.  │
│  ┌──────────┴────────────┐      └───────────────┘
│  │        check          │
│  └──────────┬────────────┘
│  ┌──────────┴────────────┐
└──┤    close callbacks    │
   └───────────────────────┘
注意:每個(gè)方框?qū)⒈环Q為事件循環(huán)的“階段”。

每個(gè)階段都有一個(gè)執(zhí)行回調(diào)的FIFO(First In First Out,先進(jìn)先出)隊(duì)列。 雖然每個(gè)階段都有其特定的方式,但通常情況下,當(dāng)事件循環(huán)進(jìn)入給定階段時(shí),它將執(zhí)行特定于該階段的任何操作,然后在該階段的隊(duì)列中執(zhí)行回調(diào),直到隊(duì)列耗盡或回調(diào)的最大數(shù)量已執(zhí)行。 當(dāng)隊(duì)列耗盡或達(dá)到回調(diào)限制時(shí),事件循環(huán)將移至下一個(gè)階段,依此類(lèi)推。

由于這些操作中的任何一個(gè)都可以調(diào)度更多的操作,并且在輪詢階段處理的新事件由內(nèi)核排隊(duì),所以輪詢事件可以在輪詢事件正在處理的同時(shí)排隊(duì)。 因此,長(zhǎng)時(shí)間運(yùn)行的回調(diào)可以使輪詢階段的運(yùn)行時(shí)間遠(yuǎn)遠(yuǎn)超過(guò)計(jì)時(shí)器的閾值。有關(guān)更多詳細(xì)信息,請(qǐng)參閱定時(shí)器和輪詢部分。

注意:Windows和Unix / Linux實(shí)現(xiàn)之間略有差異,但這對(duì)此演示并不重要。 最重要的部分在這里。 實(shí)際上有七八個(gè)步驟,但我們關(guān)心的那些 - Node.js實(shí)際使用的那些 - 就是上述那些。
階段概述

定時(shí)器(timers):此階段執(zhí)行由setTimeout()setInterval()調(diào)度的回調(diào)。

I / O 回調(diào)函數(shù):執(zhí)行幾乎所有的回調(diào)函數(shù),除了關(guān)閉回調(diào)函數(shù),定時(shí)器計(jì)劃的回調(diào)函數(shù)和setImmediate()

閑置,準(zhǔn)備(idle, prepare):只在Node內(nèi)部使用。

輪詢(poll):檢索新的I / O事件; 適當(dāng)時(shí)節(jié)點(diǎn)將在此處阻斷進(jìn)程。

檢查(check):setImmediate()回調(diào)在這里被調(diào)用。

關(guān)閉回調(diào)(close callbacks):例如 socket.on("close",...)。

在事件循環(huán)的每次運(yùn)行之間,Node.js檢查它是否正在等待任何異步I / O或定時(shí)器,并在沒(méi)有任何異步I / O或定時(shí)器時(shí)清除關(guān)閉。

階段詳情

定時(shí)器

計(jì)時(shí)器指定閾值,之后可以執(zhí)行提供的回調(diào),而不是人們希望執(zhí)行的確切時(shí)間。 定時(shí)器回調(diào)將在指定的時(shí)間過(guò)后,按照預(yù)定的時(shí)間運(yùn)行; 但是,操作系統(tǒng)調(diào)度或其他回調(diào)的運(yùn)行可能會(huì)延遲它們。

注意:從技術(shù)上講,輪詢階段控制何時(shí)執(zhí)行定時(shí)器。

例如,假設(shè)您計(jì)劃在100 ms閾值后執(zhí)行超時(shí),那么您的腳本將異步開(kāi)始讀取需要95 ms的文件:

const fs = require("fs");

function someAsyncOperation(callback) {
  // 假設(shè)這個(gè)讀取將用耗時(shí)95ms
  fs.readFile("/path/to/file", callback);
}

const timeoutScheduled = Date.now();

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

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


// 執(zhí)行一些異步操作將耗時(shí) 95ms
someAsyncOperation(() => {
  const startCallback = Date.now();

  // 執(zhí)行一些可能耗時(shí)10ms的操作
  while (Date.now() - startCallback < 10) {
    // do nothing
  }
});

當(dāng)事件循環(huán)進(jìn)入輪詢階段時(shí),它有一個(gè)空隊(duì)列(fs.readFile()尚未完成),因此它將等待剩余的毫秒數(shù),直到達(dá)到最快計(jì)時(shí)器的閾值。 當(dāng)它等待95ms傳遞時(shí),fs.readFile()完成讀取文件,并且需要10ms完成的回調(diào)被添加到輪詢隊(duì)列并執(zhí)行。 當(dāng)回調(diào)完成時(shí),隊(duì)列中沒(méi)有更多的回調(diào),所以事件循環(huán)會(huì)看到已經(jīng)達(dá)到最快計(jì)時(shí)器的閾值,然后回到計(jì)時(shí)器階段以執(zhí)行計(jì)時(shí)器的回調(diào)。 在這個(gè)例子中,你會(huì)看到被調(diào)度的定時(shí)器和它正在執(zhí)行的回調(diào)之間的總延遲將是105ms。

注意:為防止輪詢階段進(jìn)入惡性事件循環(huán),在停止輪詢之前,libuv(實(shí)現(xiàn)Node.js事件循環(huán)的C庫(kù)以及平臺(tái)的所有異步行為)也有一個(gè)硬性最大值(取決于系統(tǒng))來(lái)停止輪詢更多的事件。

I / O回調(diào)

此階段為某些系統(tǒng)操作(如TCP錯(cuò)誤類(lèi)型)執(zhí)行回調(diào)。 例如,如果嘗試連接時(shí)TCP套接字收到ECONNREFUSED,則某些* nix系統(tǒng)要等待報(bào)告錯(cuò)誤。 這將排隊(duì)在I / O回調(diào)階段執(zhí)行。

輪詢

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

執(zhí)行已過(guò)時(shí)的定時(shí)器腳本;

處理輪詢隊(duì)列中的事件。

當(dāng)事件循環(huán)進(jìn)入輪詢階段并且沒(méi)有計(jì)時(shí)器時(shí),會(huì)發(fā)生以下兩件事之一:

如果輪詢隊(duì)列不為空,則事件循環(huán)將遍歷其回調(diào)隊(duì)列,同步執(zhí)行它們,直到隊(duì)列耗盡或達(dá)到系統(tǒng)相關(guān)硬限制。

如果輪詢隊(duì)列為,則會(huì)發(fā)生以下兩件事之一:

1)如果腳本已通過(guò)setImmediate()進(jìn)行調(diào)度,則事件循環(huán)將結(jié)束輪詢階段并繼續(xù)執(zhí)行檢查階段以執(zhí)行這些預(yù)定腳本。
2)如果腳本沒(méi)有通過(guò)setImmediate()進(jìn)行調(diào)度,則事件循環(huán)將等待回調(diào)被添加到隊(duì)列中,然后立即執(zhí)行它們。

一旦輪詢隊(duì)列為空,事件循環(huán)將檢查已達(dá)到時(shí)間閾值的定時(shí)器。 如果一個(gè)或多個(gè)定時(shí)器準(zhǔn)備就緒,則事件循環(huán)將回退到定時(shí)器階段以執(zhí)行這些定時(shí)器的回調(diào)。

檢查check

此階段允許在輪詢階段結(jié)束后立即執(zhí)行回調(diào)。 如果輪詢階段變得空閑并且腳本已經(jīng)使用setImmediate()排隊(duì),則事件循環(huán)可能會(huì)繼續(xù)檢查階段而不是等待。

setImmediate()實(shí)際上是一個(gè)特殊的定時(shí)器,它在事件循環(huán)的一個(gè)多帶帶的階段中運(yùn)行。 它使用libuv API來(lái)調(diào)度回調(diào),以在輪詢階段完成后執(zhí)行。

通常,隨著代碼的執(zhí)行,事件循環(huán)將最終進(jìn)入輪詢階段,在那里它將等待傳入的連接,請(qǐng)求等。但是,如果使用setImmediate()計(jì)劃了回調(diào)并且輪詢階段變?yōu)榭臻e, 將結(jié)束并繼續(xù)進(jìn)行檢查階段,而不是等待輪詢事件。

關(guān)閉回調(diào)

如果套接字或句柄突然關(guān)閉(例如socket.destroy()),則在此階段將發(fā)出"close"事件。 否則它將通過(guò)process.nextTick()發(fā)出。

setImmediate()vs setTimeout()

setImmediate()setTimeout()是相似的,但取決于它們何時(shí)被調(diào)用,其行為方式不同。

setImmediate()用于在當(dāng)前輪詢階段完成后執(zhí)行腳本。

setTimeout()計(jì)劃腳本在經(jīng)過(guò)最小閾值(以毫秒為單位)后運(yùn)行。

定時(shí)器執(zhí)行的順序取決于它們被調(diào)用的上下文。 如果兩者都是在主模塊內(nèi)調(diào)用的,那么時(shí)序?qū)⑹艿竭M(jìn)程性能的限制(可能會(huì)受到計(jì)算機(jī)上運(yùn)行的其他應(yīng)用程序的影響)。

例如,如果我們運(yùn)行以下不在I / O周期內(nèi)的腳本(即主模塊),則兩個(gè)定時(shí)器的執(zhí)行順序是非確定性的,因?yàn)樗苓^(guò)程執(zhí)行的約束:

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

setImmediate(() => {
  console.log("immediate");
});

$ node timeout_vs_immediate.js
timeout
immediate
$ node timeout_vs_immediate.js
immediate
timeout

但是,如果在I / O周期內(nèi)移動(dòng)這兩個(gè)調(diào)用,則立即回調(diào)總是首先執(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()超過(guò)setTimeout()的的主要優(yōu)點(diǎn)是,如果在I / O周期內(nèi)進(jìn)行調(diào)度,將始終在任何計(jì)時(shí)器之前執(zhí)行setImmediate(),而不管有多少個(gè)計(jì)時(shí)器。

process.nextTick()

理解process.nextTick()

您可能已經(jīng)注意到process.nextTick()沒(méi)有顯示在圖中,即使它是異步API的一部分。 這是因?yàn)?b>process.nextTick()在技術(shù)上并不是事件循環(huán)的一部分。 相反,nextTickQueue將在當(dāng)前操作完成后(階段轉(zhuǎn)換)處理,而不管事件循環(huán)的當(dāng)前階段如何。

回顧一下我們的圖,只要你在給定的階段調(diào)用process.nextTick(),所有傳遞給process.nextTick()的回調(diào)都將在事件循環(huán)繼續(xù)之前被解析。 這可能會(huì)造成一些不好的情況,因?yàn)樗试S您通過(guò)遞歸process.nextTick()調(diào)用來(lái)“堵塞”您的I / O,從而防止事件循環(huán)到達(dá)輪詢階段。

為什么會(huì)被允許?

為什么像這樣的東西被包含在Node.js中? 其中一部分是一種設(shè)計(jì)理念,即即使不需要,API也應(yīng)該始終是異步的。 以此代碼片段為例:

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

代碼片段進(jìn)行參數(shù)檢查,如果不正確,它會(huì)將錯(cuò)誤傳遞給回調(diào)函數(shù)。 最近更新的API允許將參數(shù)傳遞給process.nextTick(),以允許它將回調(diào)后傳遞的任何參數(shù)作為參數(shù)傳播給回調(diào)函數(shù),因此您不必嵌套函數(shù)。

我們正在做的是將錯(cuò)誤傳遞給用戶,但只有在我們?cè)试S執(zhí)行其余用戶的代碼之后。 通過(guò)使用process.nextTick(),我們保證apiCall()總是在用戶代碼的其余部分之后并且允許事件循環(huán)繼續(xù)之前運(yùn)行其回調(diào)。 為了達(dá)到這個(gè)目的,JS調(diào)用堆棧被允許展開(kāi),然后立即執(zhí)行提供的回調(diào),允許人們對(duì)process.nextTick()進(jìn)行遞歸調(diào)用,而不會(huì)出現(xiàn)RangeError:超出v8的最大調(diào)用堆棧大小。

這種理念會(huì)導(dǎo)致一些潛在的問(wèn)題。 以此片段為例:

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;

用戶定義someAsyncApiCall()具有異步簽名,但它實(shí)際上是同步運(yùn)行的。 當(dāng)它被調(diào)用時(shí),提供給someAsyncApiCall()的回調(diào)將在事件循環(huán)的相同階段被調(diào)用,因?yàn)?b>someAsyncApiCall()實(shí)際上并不會(huì)異步執(zhí)行任何操作。 因此,回調(diào)會(huì)嘗試引用欄,即使它在范圍中可能沒(méi)有該變量,因?yàn)樵撃_本無(wú)法運(yùn)行到完成狀態(tài)。

通過(guò)將回調(diào)放置在process.nextTick()中,腳本仍然具有運(yùn)行到完成的能力,允許在調(diào)用回調(diào)之前對(duì)所有變量,函數(shù)等進(jìn)行初始化。 它還具有不允許事件循環(huán)繼續(xù)的優(yōu)點(diǎn)。 在事件循環(huán)被允許繼續(xù)之前,用戶被告知錯(cuò)誤可能是有用的。 以下是使用process.nextTick()的前一個(gè)示例:

let bar;

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

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

bar = 1;

這是另一個(gè)現(xiàn)實(shí)的例子:

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

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

當(dāng)只有一個(gè)端口通過(guò)時(shí),該端口會(huì)立即綁定。 所以,"listening"回調(diào)可以立即被調(diào)用。 問(wèn)題是.on("listening")回調(diào)不會(huì)在那個(gè)時(shí)候設(shè)置。

為了解決這個(gè)問(wèn)題,"listening"事件在nextTick()中排隊(duì)等待腳本運(yùn)行完成。 這允許用戶設(shè)置他們想要的任何事件處理程序。

process.nextTick()vs setImmediate()

就用戶而言,我們有兩個(gè)類(lèi)似的調(diào)用,但他們的名字很混亂。

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

setImmediate()觸發(fā)以下迭代或事件循環(huán)的“打勾”

實(shí)質(zhì)上,名稱應(yīng)該交換。 process.nextTick()setImmediate()立即觸發(fā)更多,但這是過(guò)去的人為因素,不太可能改變。 制作這個(gè)開(kāi)關(guān)會(huì)在npm上打破大部分的軟件包。 每天都有更多的新模塊被添加,這意味著我們每天都在等待,發(fā)生更多潛在的破壞。 雖然他們混淆,名字本身不會(huì)改變。

我們建議開(kāi)發(fā)人員在所有情況下使用setImmediate(),因?yàn)樗菀淄评恚ú⑶視?huì)導(dǎo)致代碼與更廣泛的環(huán)境兼容,如瀏覽器JS)。

為什么使用process.nextTick()?

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

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

有時(shí)需要在調(diào)用堆棧解除后,但事件循環(huán)繼續(xù)之前,允許回調(diào)運(yùn)行。

一個(gè)例子是匹配用戶的期望。 簡(jiǎn)單的例子:

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

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

假設(shè)listen()在事件循環(huán)的開(kāi)始處運(yùn)行,但監(jiān)聽(tīng)回調(diào)放置在setImmediate()中。 除非傳遞主機(jī)名,否則綁定到端口將立即發(fā)生。 要繼續(xù)進(jìn)行事件循環(huán),它必須進(jìn)入輪詢階段,這意味著有一個(gè)非零的機(jī)會(huì)可以收到連接,允許在監(jiān)聽(tīng)事件之前觸發(fā)連接事件。

另一個(gè)例子是運(yùn)行一個(gè)函數(shù)構(gòu)造函數(shù),該函數(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", () => {
  console.log("an event occurred!");
});

您不能立即從構(gòu)造函數(shù)發(fā)出事件,因?yàn)槟_本不會(huì)處理到用戶為該事件分配回調(diào)的位置。 因此,在構(gòu)造函數(shù)本身中,可以使用process.nextTick()在構(gòu)造函數(shù)完成后設(shè)置一個(gè)回調(diào)來(lái)發(fā)出事件,這會(huì)提供預(yù)期的結(jié)果:

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

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

  // 一旦處理程序被分配,使用nextTick來(lái)發(fā)出事件
  process.nextTick(() => {
    this.emit("event");
  });
}
util.inherits(MyEmitter, EventEmitter);

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

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

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

相關(guān)文章

  • JS異步詳解 - 瀏覽器/Node/事件循環(huán)/消息隊(duì)列/宏任務(wù)/微任務(wù)

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

    awesome23 評(píng)論0 收藏0
  • Node.js】理解事件循環(huán)機(jī)制

    摘要:前沿是基于引擎的運(yùn)行環(huán)境具有事件驅(qū)動(dòng)非阻塞等特點(diǎn)結(jié)合具有網(wǎng)絡(luò)編程文件系統(tǒng)等服務(wù)端的功能用庫(kù)進(jìn)行異步事件處理線程的單線程含義實(shí)際上說(shuō)的是執(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
  • 瀏覽器與Node事件循環(huán)(Event Loop)有何區(qū)別?

    摘要:事件觸發(fā)線程主要負(fù)責(zé)將準(zhǔn)備好的事件交給引擎線程執(zhí)行。它將不同的任務(wù)分配給不同的線程,形成一個(gè)事件循環(huán),以異步的方式將任務(wù)的執(zhí)行結(jié)果返回給引擎。 Fundebug經(jīng)作者浪里行舟授權(quán)首發(fā),未經(jīng)同意請(qǐng)勿轉(zhuǎn)載。 前言 本文我們將會(huì)介紹 JS 實(shí)現(xiàn)異步的原理,并且了解了在瀏覽器和 Node 中 Event Loop 其實(shí)是不相同的。 一、線程與進(jìn)程 1. 概念 我們經(jīng)常說(shuō) JS 是單線程執(zhí)行的,...

    TANKING 評(píng)論0 收藏0
  • JavaScript Event loop 事件循環(huán)

    摘要:階段有兩個(gè)主要功能也會(huì)執(zhí)行時(shí)間定時(shí)器到達(dá)期望時(shí)間的回調(diào)函數(shù)執(zhí)行事件循環(huán)列表里的函數(shù)當(dāng)進(jìn)入階段并且沒(méi)有其余的定時(shí)器,那么如果事件循環(huán)列表不為空,則迭代同步的執(zhí)行隊(duì)列中的函數(shù)。如果沒(méi)有,則等待回調(diào)函數(shù)進(jìn)入隊(duì)列并立即執(zhí)行。 Event Loop 本文以 Node.js 為例,講解 Event Loop 在 Node.js 的實(shí)現(xiàn),原文,JavaScript 中的實(shí)現(xiàn)大同小異。 什么是 Eve...

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

    摘要:通過(guò)查看的文檔可以發(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)論

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