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

資訊專欄INFORMATION COLUMN

Nodejs高性能原理(下) --- 事件循環(huán)詳解

newsning / 1378人閱讀

摘要:如果一個即時定時器是被一個正在執(zhí)行的回調排入隊列的,則該定時器直到下一次事件循環(huán)迭代才會被觸發(fā)。參數(shù)描述在事件循環(huán)的當前回合結束時要調用的函數(shù)。事件輪詢隨后的調用,會在任何事件包括定時器之前運行。

系列文章

Nodejs高性能原理(上) --- 異步非阻塞事件驅動模型
Nodejs高性能原理(下) --- 事件循環(huán)詳解

前言

終于開始我nodejs的博客生涯了,先從基本的原理講起.以前寫過一篇瀏覽器執(zhí)行機制的文章,和nodejs的相似之處還是挺多的,不熟悉可以去看看先.
Javascript執(zhí)行機制--單線程,同異步任務,事件循環(huán)

寫下來之后可能還是有點懞,以后慢慢補充,也歡迎指正,特別是那篇翻譯文章后面已經(jīng)看不懂了.有人出手科普一下就好了.因為懶得動手做,整篇文章的圖片要么來源官網(wǎng),要么來源百度圖片.
補充: 當前Nodejs版本10.3.0
2019/8/13 修改部分描述內容

Nodejs事件循環(huán)詳解

基本來自The Node.js Event Loop, Timers, and process.nextTick(),可以說這部分我就是翻譯功能,部分翻譯太繞口會和諧一下,基本忠于原文.

當nodejs開始運行的時候會初始化事件循環(huán),處理所提供的輸入腳本或者放置進REPL(Read Eval Print Loop:交互式解釋器類似 Window 系統(tǒng)的終端或 Unix/Linux shell),可能會進行異步API調用.定時器調度,或者process.nextTick(),然后開始處理事件循環(huán)的流程.

下面來自官網(wǎng)的炫酷流程代碼示意圖(官網(wǎng)直接用符號拼湊出來,這里因為編輯器問題衹能截圖)

注意: 每個框都被稱為事件循環(huán)的一個流程階段.

每個階段都有一個FIFO(先進先出)執(zhí)行回調函數(shù)的隊列,然而每個階段都有其獨特之處.通常當事件循環(huán)進入到給定階段會執(zhí)行特定于該階段的所有操作.然后執(zhí)行該階段隊列的回調事件直到隊列耗盡或者超過最大執(zhí)行限度為止,然后事件循環(huán)就會走向下一階段,以此類推.

因為這些操作可能會調度更多的操作并且在poll階段中新的處理事件會加入到內核的隊列,即處理輪詢事件時候又加入新的輪詢事件,因此,長時間運行回調事件會讓poll階段運行時間超過定時器的閾值.

階段綜述:

timers(定時器): 這階段執(zhí)行setTimeoutsetInterval調度的回調;

pending callbacks(等待回調): 推遲到下一次循環(huán)迭代執(zhí)行I/O回調;

idle,prepare(閑置,準備): 只能內部使用;

poll(輪詢): 檢索新的I/O事件;執(zhí)行I/O相關回調(除了close callbacks以外,大多數(shù)是定時器調度,和setImmediate()),當運行時候適當條件下nodejs會占用阻塞;

check(檢測): setImmediate()回調就在這執(zhí)行;

close callbacks(關閉回調): 一些關閉回調,例如socket.on("close", ...),

在事件循環(huán)的每次運行過程中,nodejs會檢測是否有任何待處理的異步I/O或者定時器,沒有的話就徹底清除關閉.

Timers(定時器)

在定時器設定了一個閾值之后,被提供的回調函數(shù)實際執(zhí)行時間可能不是開發(fā)者想要它被執(zhí)行的時間,定時器回調會在指定閾值過去后盡可能早的運行,然而操作系統(tǒng)調度或者其他回調運行都可能會導致延遲.
注意: 為了防止輪詢階段持續(xù)時間太長,libuv 會根據(jù)操作系統(tǒng)的不同設置一個輪詢的上限。(這就是為什么上面會說執(zhí)行該階段隊列的回調事件直到隊列耗盡或者超過最大執(zhí)行限度為止)
(下面會多帶帶詳細講解定時器的東西)

pending callbacks(等待回調)

這階段會執(zhí)行一些系統(tǒng)操作回調像TCP錯誤類型,例如當一個TCP socket想要連接的時候接收到ECONNREFUSED,一些*nix系統(tǒng)會等待錯誤報文,這會被排在pending callbacks 階段執(zhí)行.

poll(輪詢)

這階段有兩個主要功能:

計算它應該阻塞多長的時間和進行輪詢I/O操作;
(原文: Calculating how long it should block and poll for I/O, then,我看到有些人會翻譯成當 timers 的定時器到期后,執(zhí)行定時器(setTimeout 和 setInterval)的 callback。不知道版本不對還是我翻譯不對味)

處理poll隊列事件;

當事件循環(huán)進入poll階段,并且沒有timers調度,會發(fā)生其中一種情況:

如果poll隊列不為空,事件循環(huán)會迭代回調隊列同步執(zhí)行它們直到隊列耗盡或者到達系統(tǒng)限制;

如果poll隊列為空,一件或者多件情況會發(fā)生:

如果setImmediate()腳本已經(jīng)被調度,事件循環(huán)的poll階段完成然后繼續(xù)到check階段去執(zhí)行那里的調度腳本;

如果setImmediate()腳本還沒被調度,事件循環(huán)會等待回調被添加到隊列,然后立即執(zhí)行.

一旦poll隊列清空了事件循環(huán)會檢測有沒有定時器閾值是否到達,如果一個或多個定時器已經(jīng)準備好,事件循環(huán)會繞回到timers階段去執(zhí)行它們的定時器回調函數(shù).

check(檢測)

這階段允許開發(fā)者在poll階段完成之后立即執(zhí)行回調函數(shù),如果poll階段在閑置中并且腳本已經(jīng)被setImmediate()加入隊列,事件循環(huán)會跳到check階段而不是等待.

setImmediate()實際上是一個特殊的定時器,它會在事件循環(huán)的多帶帶階段運行.通過libuv API在poll階段完成之后調度回調去執(zhí)行.

一般來說,當代碼執(zhí)行完,事件循環(huán)最終會到達poll階段去等待即將到來的連接,請求等等.然而,如果一個回調函數(shù)被setImmediate()調度并且poll階段是閑置狀態(tài),它會結束并且跳到check階段而不是在等待輪詢事件.

close callbacks(關閉回調)

如果一個sockethandle突然被關閉(例如socket.destroy()),"close"事件會在這階段被觸發(fā),否則會通過process.nextTick()被觸發(fā).

非異步API(強勢插樓)

事件循環(huán)階段部分已經(jīng)講完了,剩下的是定時器之間區(qū)別部分,在那之前我想在這里補充一下定時器知識!

Node.js 中的計時器函數(shù)實現(xiàn)使用了一個與瀏覽器類似但不同的內部實現(xiàn),它是基于 Node.js 事件循環(huán)構建的。

瀏覽器定時器 setTimeout(callback,delay,lang) :

在指定的毫秒數(shù)后調用函數(shù)或計算表達式,返回一個用于 clearTimeout() 的Timeout或窗口被關閉。

參數(shù) 描述
callback 必需。要調用的函數(shù)后要執(zhí)行的 JavaScript 代碼串。
delay 必需。在執(zhí)行代碼前需等待的毫秒數(shù), W3C標準規(guī)定時間間隔低于4ms被算為4ms,具體看瀏覽器
lang 可選。腳本語言可以是:JScript VBScript JavaScript
setInterval(callback,delay,lang) :

按照指定的周期(以毫秒計)來調用函數(shù)或計算表達式。方法會不停地調用函數(shù),返回一個用于 clearInterval() 的Timeout或窗口被關閉。
參數(shù)請看上面setTimeout.

nodejs定時器 setTimeout(callback, delay[, ...args])

在指定的毫秒數(shù)后調用函數(shù)或計算表達式,返回一個用于 clearTimeout() 的Timeout或窗口被關閉。

參數(shù) 描述
callback 必需。要調用的函數(shù)后要執(zhí)行的 JavaScript 代碼串。
delay 必需。在執(zhí)行代碼前需等待的毫秒數(shù)。當 delay 大于 2147483647 或小于 1 時,delay 會被設為 1。
...args 可選, 當調用 callback 時要傳入的可選參數(shù)。

此外還增加一些方法timeout.ref(),timeout.unref()等,請自行查看.Timeout 類

setInterval(callback, delay[, ...args])

按照指定的周期(以毫秒計)來調用函數(shù)或計算表達式。方法會不停地調用函數(shù),返回一個用于 clearInterval() 的Timeout或窗口被關閉。
參數(shù)請看上面setTimeout.

setImmediate(callback[, ...args])

預定立即執(zhí)行的 callback,它是在 I/O 事件的回調之后被觸發(fā)。 返回一個用于 clearImmediate() 的 Immediate。
當多次調用 setImmediate() 時,callback 函數(shù)會按照它們被創(chuàng)建的順序依次執(zhí)行。 每次事件循環(huán)迭代都會處理整個回調隊列。 如果一個即時定時器是被一個正在執(zhí)行的回調排入隊列的,則該定時器直到下一次事件循環(huán)迭代才會被觸發(fā)。

參數(shù) 描述
callback 在 Node.js 事件循環(huán)的當前回合結束時要調用的函數(shù)。
...args 可選, 當調用 callback 時要傳入的可選參數(shù)。

對應的清除方法clearImmediate(),此外還增加一些方法setImmediate.ref(),setImmediate.unref()等,請自行查看.Immediate 類

promise寫法(題外話)

可用util.promisify()提供的promises常用變體

const util = require("util");
const setTimeoutPromise = util.promisify(setTimeout),
  setImmediatePromise = util.promisify(setImmediate);

setTimeoutPromise(40, "foobar").then(value => {
  // value === "foobar" (passing values is optional)
  // This is executed after about 40 milliseconds.
});

setImmediatePromise("foobar").then(value => {
  // value === "foobar" (passing values is optional)
  // This is executed after all I/O callbacks.
});

// or with async function
async function timerExample() {
  console.log("Before I/O callbacks");
  await setImmediatePromise();
  console.log("After I/O callbacks");
}
timerExample();
process.nextTick(callback[, ...args])

將 callback 添加到next tick 隊列。 一旦當前事件輪詢隊列的任務全部完成,在next tick隊列中的所有callbacks會被依次調用。但是不同于上面的定時器.在內部的處理機制不同,nextTick擁有比延時更多的特性.
注意:這不是定時器,而且遞歸調用nextTick callbacks 會阻塞任何I/O操作,就像一個while(true)循環(huán)一樣

參數(shù) 描述
callback 一旦當前事件輪詢隊列的任務全部完成,在next tick隊列中要調用的函數(shù)
...args 可選, 當調用 callback 時要傳入的可選參數(shù)。
事件輪詢隨后的ticks 調用,會在任何I/O事件(包括定時器)之前運行。
console.log("start");
process.nextTick(() => {
  console.log("nextTick callback");
});
console.log("scheduled");
// Output:
// start
// scheduled
// nextTick callback
在對象構造好但還沒有任何I/O發(fā)生之前,想給用戶機會來指定某些事件處理器。
function MyThing(options) {
  this.setupOptions(options);

  process.nextTick(() => {
    this.startDoingStuff();
  });
}

const thing = new MyThing();
thing.getReadyForStuff();

// thing.startDoingStuff() gets called now, not before.
每次事件輪詢后,在額外的I/O執(zhí)行前,next tick隊列都會優(yōu)先執(zhí)行。
//使用場景
const maybeTrue = Math.random() > 0.5;

maybeSync(maybeTrue, () => {
  foo();
});

bar();

//危險寫法,因為不清楚foo() 或 bar() 哪個會被先調用
function maybeSync(arg, cb) {
  if (arg) {
    cb();
    return;
  }

  fs.stat("file", cb);
}

//優(yōu)化寫法,每次事件輪詢后,在額外的I/O執(zhí)行前,next tick隊列都會優(yōu)先執(zhí)行
function definitelyAsync(arg, cb) {
  if (arg) {
    process.nextTick(cb);
    return;
  }

  fs.stat("file", cb);
}
繼續(xù)回到文章 setImmediate() vs setTimeout()

setImmediate() vs setTimeout()很相似,但是行為方式的不同取決于他們調用時機.

setImmediate()被設計為在當前poll階段完成之后執(zhí)行腳本.

setTimeout()會在消耗一段時間閾值之后調度一段腳本去運行.

定時器被執(zhí)行時候的順序變化取決于它們被調用時候的上下文,如果都是在主模塊內部被調用會受到進程性能的約束(可能被本機其他應用運行影響);

例如,如果我們不在I/O循環(huán)運行下面的腳本(也就是在主模塊中),兩個定時器的執(zhí)行順序是不確定的,因為它們受到進程性能的約束.

// 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

可是如果你把兩個代碼放進I/O循環(huán)內部,immediate()回調函數(shù)總是先執(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()的主要優(yōu)勢是如果在I/O循環(huán)內部調用,setImmediate()總會在所有定時器之前執(zhí)行,與你定義多少個定時器無關.

理解process.nextTick()

你可能已經(jīng)注意到process.nextTick()并沒有出現(xiàn)在圖表,雖然它是異步API的一部分,那是因為process.nextTick()技術上不是事件循環(huán)部分.相反,process.nextTick()會在當前操作完成之后被處理,不管事件循環(huán)的當前階段如何.

回顧我們的圖表,在給定階段的任何時候你調用process.nextTick(),傳遞給process.nextTick()的回調函數(shù)都會在事件循環(huán)繼續(xù)之前被解決,這會造成一些糟糕情況因為它允許你通過執(zhí)行遞歸process.nextTick()調用去"餓死"(starve)你的I/O,從而阻止事件循環(huán)到達poll階段.

為什么會被允許?

為什么一些像這樣的內容會被包含在Nodejs?這部分是因為它是一種設計哲學,API應該總是異步即使它并不需要,看這段代碼片段例子

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

這片段會檢查入?yún)?如果不正確會傳遞錯誤到回調函數(shù),最近更新的API允許傳遞入?yún)⒌絧rocess.nextTick(),允許他在回調后取傳遞的任何參數(shù)作為回調的入?yún)?這樣就不必嵌套函數(shù)了.

這句又長又繞口,附上部分原文:
The API updated fairly recently to allow passing arguments to process.nextTick() allowing it to take any arguments passed after the callback to be propagated as the arguments to the callback so you don"t have to nest functions.

我們要做的是傳遞一個錯誤給開發(fā)者但僅僅是我們已經(jīng)允許開發(fā)者其余的代碼執(zhí)行之后.通過使用process.nextTick()我們保證apiCall()總會在開發(fā)者其余代碼執(zhí)行之后事件循環(huán)允許執(zhí)行之前運行它的回調函數(shù),為了實現(xiàn)這一步,JS調用堆棧允許展開立即執(zhí)行所提供的回調函數(shù),允許開發(fā)者執(zhí)行遞歸調用process.nextTick()而不會達到引用錯誤: Maximum call stack size exceeded from v8.

這句又長又繞口,附上原文:
What we"re doing is passing an error back to the user but only after we have allowed the rest of the user"s code to execute. By using process.nextTick() we guarantee that apiCall() always runs its callback after the rest of the user"s code and before the event loop is allowed to proceed. To achieve this, the JS call stack is allowed to unwind then immediately execute the provided callback which allows a person to make recursive calls to process.nextTick() without reaching a RangeError: Maximum call stack size exceeded from v8.

這種哲學會導致一些潛在的有問題的情況,看看這段片段例子

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;

開發(fā)者定義someAsyncApiCall()有一個異步簽名(signature??),實際上卻是同步操作,當它調用時候提供給someAsyncApiCall()的回調函數(shù)會在事件循環(huán)的相同階段被調用因為someAsyncApiCall()實際上并沒有做任何異步事情,結果回調函數(shù)試著去引用bar即使它可能還沒在作用域里,因為代碼不可能運行完成.

但是如果把它放進process.nextTick(),代碼依舊有能力跑完,允許所有變量,函數(shù)等等在回調函數(shù)被調用之前優(yōu)先初始化完,它具有不讓事件循環(huán)繼續(xù)的優(yōu)點,在允許事件循環(huán)繼續(xù)之前,提醒用戶注意錯誤可能是有用的。

這句又長又繞口,附上原文:
The user defines someAsyncApiCall() to have an asynchronous signature, but it actually operates synchronously. When it is called, the callback provided to someAsyncApiCall() is called in the same phase of the event loop because someAsyncApiCall() doesn"t actually do anything asynchronously. As a result, the callback tries to reference bar even though it may not have that variable in scope yet, because the script has not been able to run to completion.

By placing the callback in a process.nextTick(), the script still has the ability to run to completion, allowing all the variables, functions, etc., to be initialized prior to the callback being called. It also has the advantage of not allowing the event loop to continue. It may be useful for the user to be alerted to an error before the event loop is allowed to continue. Here is the previous example using process.nextTick():

這是上面使用process.nextTick()的例子

let bar;

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

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

bar = 1;

這是另一個現(xiàn)實世界的例子:

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

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

(這句又長又繞口,不想翻了:)
When only a port is passed, the port is bound immediately. So, the "listening" callback could be called immediately. The problem is that the .on("listening") callback will not have been set by that time.

想要避開這問題,"listening"事件會加入nextTick()隊列以容許腳本運行完,這允許開發(fā)者設置任何他們想要的任何事件處理器.

process.nextTick() vs setImmediate()

就用戶而言,我們有兩個類似的調用,不過他們的名字令人困惑.
process.nextTick() 在同一階段立刻觸發(fā)(原文fires: 點燃;解雇;開除;使發(fā)光;燒制;激動;放槍???)
setImmediate() 在事件循環(huán)的后續(xù)迭代或“tick”中觸發(fā)(原文fires)

本質上,名字應該調換,process.nextTick()比setImmediate()更加容易觸發(fā),但這是一種不可變得的過去的產物,這種轉換會在npm中破壞大量的包,每天都有很多新包被添加,意味著我們每等待一天就有更多潛在的破壞發(fā)生,即使它們多困惑也不能更改它們的名字.

我們建議開發(fā)者們在任何情況使用setImmediate()因為它容易推出(reason about??)(它會讓代碼兼容更廣泛的環(huán)境變量,像browser JS)

為什么使用process.nextTick()?(翻譯文章最后內容)

兩個原因:
1, 允許開發(fā)者們處理錯誤,清除任何不需要的資源,或者嘗試在事件循環(huán)繼續(xù)之前再次發(fā)起請求.
2, 在需要的時候允許調用棧釋放(unwound??)之后但事件循環(huán)繼續(xù)之前運行一個回調函數(shù).

一個符合開發(fā)者們期望的簡單例子

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

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

假設listen()在事件循環(huán)開始的時候運行,但是監(jiān)聽回調被放置在setImmediate()。除非傳遞主機名立即綁定端口,想讓事件循環(huán)繼續(xù)進行必須進入poll階段,意味著有機會(a non-zero chance??)已經(jīng)接收到一個連接,允許在監(jiān)聽事件之前觸發(fā)連接事件。

(有段名詞不懂怎么翻譯:)
which means there is a non-zero chance that a connection could have been received allowing the connection event to be fired before the listening event

另一個例子是運行構造函數(shù),從EventEmitter繼承并且想要在構造函數(shù)內部調用一個事件。

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!");
});

我們不能在構造函數(shù)立刻發(fā)出事件是因為腳本可能還沒處理到開發(fā)者設置觸發(fā)事件回調函數(shù)的位置,所以在構造函數(shù)內部本身你能使用process.nextTick()設置觸發(fā)事件回調函數(shù)以在構造函數(shù)已經(jīng)完成之后提供期望結果。

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(() => {
    this.emit("event");
  });
}
util.inherits(MyEmitter, EventEmitter);

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

你們試試看這個輸出順序符不符合你們預期

const fs = require("fs");

console.log("start");
setTimeout(function timeout() {
  console.log("模塊外部timeout");
}, 1000);

setImmediate(function immediate() {
  console.log("模塊外部immediate");
});

process.nextTick(() => {
  console.log("模塊外部nextTick callback");
});

fs.readFile(__filename, () => {
  setTimeout(function timeout() {
    console.log("I/O內部timeout");
  }, 0);

  setImmediate(function immediate() {
    console.log("I/O內部immediate");
  });

  process.nextTick(() => {
    console.log("I/O內部nextTick callback");
  });
});

console.log("end");
// start
// end
// 模塊外部nextTick callback
// 模塊外部immediate
// I/O內部nextTick callback
// I/O內部immediate
// I/O內部timeout
// 模塊外部timeout
Nodejs劣勢

總的來說單線程的鍋.
1, 異常拋出終止
我們都知道Javascript是一門單線程語言,在發(fā)生各種錯誤之后,JavaScript引擎通常會停止,并拋出一個錯誤.
Nodejs具體錯誤直接看Error (錯誤).
暫時還沒研究到,但是肯定可以通過一些方法解決的,后補.

2, 不適合CPU密集型
盡管我們上面已經(jīng)提出了事件驅動異步IO非阻塞模型的各種優(yōu)點,但是里面有個關鍵詞叫"I/O",如果是非I/O的處理例如CPU計算還是沒改進的,如果有長時間運行的計算,將會導致CPU時間片不能釋放,使得后續(xù)I/O無法發(fā)起.
可以通過把密集運算拆分成多個小任務,減輕CPU壓力.

3, 不能用到CPU的多核
現(xiàn)在的服務器操作系統(tǒng)基本都是支持多CPU/核了,單線程言語注定只能占用一個資源,不能充分利用.

解決單線程痛點方案
可以新開進程去玩,還沒研究到不說.
process - 進程

參考資源

Node.js 中文網(wǎng) API
The Node.js Event Loop, Timers, and process.nextTick()

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

轉載請注明本文地址:http://systransis.cn/yun/106704.html

相關文章

  • Nodejs性能原理(上) --- 異步非阻塞事件驅動模型

    摘要:使用了一個事件驅動非阻塞式的模型,使其輕量又高效。的包管理器,是全球最大的開源庫生態(tài)系統(tǒng)。按照這個定義,之前所述的阻塞,非阻塞,多路復用信號驅動都屬于同步。 系列文章 Nodejs高性能原理(上) --- 異步非阻塞事件驅動模型Nodejs高性能原理(下) --- 事件循環(huán)詳解 前言 終于開始我nodejs的博客生涯了,先從基本的原理講起.以前寫過一篇瀏覽器執(zhí)行機制的文章,和nodej...

    yy736044583 評論0 收藏0
  • 優(yōu)秀文章收藏(慢慢消化)持續(xù)更新~

    摘要:整理收藏一些優(yōu)秀的文章及大佬博客留著慢慢學習原文協(xié)作規(guī)范中文技術文檔協(xié)作規(guī)范阮一峰編程風格凹凸實驗室前端代碼規(guī)范風格指南這一次,徹底弄懂執(zhí)行機制一次弄懂徹底解決此類面試問題瀏覽器與的事件循環(huán)有何區(qū)別筆試題事件循環(huán)機制異步編程理解的異步 better-learning 整理收藏一些優(yōu)秀的文章及大佬博客留著慢慢學習 原文:https://www.ahwgs.cn/youxiuwenzhan...

    JeOam 評論0 收藏0
  • JS代碼在nodejs環(huán)境執(zhí)行機制和事件循環(huán)

    摘要:開始執(zhí)行文件,同步代碼執(zhí)行完畢后,進入事件循環(huán)。時間未到的時候,如果有事件返回,就執(zhí)行該事件注冊的回調函數(shù)。對于多次執(zhí)行輸出結果不同,需要了解事件循環(huán)的基礎問題。 1. 說明 nodejs是單線程執(zhí)行的,同時它又是基于事件驅動的非阻塞IO編程模型。這就使得我們不用等待異步操作結果返回,就可以繼續(xù)往下執(zhí)行代碼。當異步事件觸發(fā)之后,就會通知主線程,主線程執(zhí)行相應事件的回調。 本篇文章講解n...

    Lowky 評論0 收藏0
  • JavaScript單線程事件循環(huán)(Event Loop)那些事

    摘要:概述本篇主要介紹的運行機制單線程事件循環(huán)結論先在中利用運行至完成和非阻塞完成單線程下異步任務的處理就是先處理主模塊主線程上的同步任務再處理異步任務異步任務使用事件循環(huán)機制完成調度涉及的內容有單線程事件循環(huán)同步執(zhí)行異步執(zhí)行定時器的事件循環(huán)開始 1.概述 本篇主要介紹JavaScript的運行機制:單線程事件循環(huán)(Event Loop). 結論先: 在JavaScript中, 利用運行至...

    Shisui 評論0 收藏0
  • JS與Node.js中的事件循環(huán)

    摘要:的單線程,與它的用途有關。特點的顯著特點異步機制事件驅動。隊列的讀取輪詢線程,事件的消費者,的主角。它將不同的任務分配給不同的線程,形成一個事件循環(huán),以異步的方式將任務的執(zhí)行結果返回給引擎。 這兩天跟同事同事討論遇到的一個問題,js中的event loop,引出了chrome與node中運行具有setTimeout和Promise的程序時候執(zhí)行結果不一樣的問題,從而引出了Nodejs的...

    abson 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<