欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Node異步和事件循環(huán)的深入講解

 更新時(shí)間:2022年07月20日 16:50:27   作者:Emma_  
異步對(duì)于前端來(lái)說(shuō)是老生常談的話題,同樣學(xué)習(xí)node也離不開(kāi)異步IO與事件循環(huán),下面這篇文章主要給大家介紹了關(guān)于Node異步和事件循環(huán)的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下

前言

Node 最初是為打造高性能的 Web 服務(wù)器而生,作為 JavaScript 的服務(wù)端運(yùn)行時(shí),具有事件驅(qū)動(dòng)、異步 I/O、單線程等特性?;谑录h(huán)的異步編程模型使 Node 具備處理高并發(fā)的能力,極大地提升服務(wù)器的性能,同時(shí),由于保持了 JavaScript 單線程的特點(diǎn),Node 不需要處理多線程下?tīng)顟B(tài)同步、死鎖等問(wèn)題,也沒(méi)有線程上下文切換所帶來(lái)的性能上的開(kāi)銷(xiāo)。基于這些特性,使 Node  具備高性能、高并發(fā)的先天優(yōu)勢(shì),并可基于它構(gòu)建各種高速、可伸縮網(wǎng)絡(luò)應(yīng)用平臺(tái)。

本文將深入 Node 異步和事件循環(huán)的底層實(shí)現(xiàn)和執(zhí)行機(jī)制,希望對(duì)你有所幫助。

為什么要異步?

Node 為什么要使用異步來(lái)作為核心編程模型呢?

前面說(shuō)過(guò),Node 最初是為打造高性能的 Web 服務(wù)器而生,假設(shè)業(yè)務(wù)場(chǎng)景中有幾組互不相關(guān)的任務(wù)要完成,現(xiàn)代主流的解決方式有以下兩種:

  • 單線程串行依次執(zhí)行。

  • 多線程并行完成。

單線程串行依次執(zhí)行,是一種同步的編程模型,它雖然比較符合程序員按順序思考的思維方式,易寫(xiě)出更順手的代碼,但由于是同步執(zhí)行 I/O,同一時(shí)刻只能處理單個(gè)請(qǐng)求,會(huì)導(dǎo)致服務(wù)器響應(yīng)速度較慢,無(wú)法在高并發(fā)的應(yīng)用場(chǎng)景下適用,且由于是阻塞 I/O,CPU 會(huì)一直等待 I/O 完成,無(wú)法做其他事情,使 CPU 的處理能力得不到充分利用,最終導(dǎo)致效率的低下,

而多線程的編程模型也會(huì)因?yàn)榫幊讨械臓顟B(tài)同步、死鎖等問(wèn)題讓開(kāi)發(fā)人員頭疼。盡管多線程在多核 CPU 上能夠有效提升 CPU 的利用率。

雖然單線程串行依次執(zhí)行和多線程并行完成的編程模型有其自身的優(yōu)勢(shì),但是在性能、開(kāi)發(fā)難度等方面也有不足之處。

除此之外,從響應(yīng)客戶(hù)端請(qǐng)求的速度出發(fā),如果客戶(hù)端同時(shí)獲取兩個(gè)資源,同步方式的響應(yīng)速度會(huì)是兩個(gè)資源的響應(yīng)速度之和,而異步方式的響應(yīng)速度會(huì)是兩者中最大的一個(gè),性能優(yōu)勢(shì)相比同步十分明顯。隨著應(yīng)用復(fù)雜度的增加,該場(chǎng)景會(huì)演變成同時(shí)響應(yīng) n 個(gè)請(qǐng)求,異步相比于同步的優(yōu)勢(shì)將會(huì)凸顯出來(lái)。

綜上所述,Node 給出了它的答案:利用單線程,遠(yuǎn)離多線程死鎖、狀態(tài)同步等問(wèn)題;利用異步 I/O,讓單線程遠(yuǎn)離阻塞,以更好地使用 CPU。這就是 Node 使用異步作為核心編程模型的原因。

此外,為了彌補(bǔ)單線程無(wú)法利用多核 CPU 的缺點(diǎn),Node 也提供了類(lèi)似瀏覽器中 Web Workers 的子進(jìn)程,該子進(jìn)程可以通過(guò)工作進(jìn)程高效地利用 CPU。

如何實(shí)現(xiàn)異步?

聊完了為什么要使用異步,那要如何實(shí)現(xiàn)異步呢?

我們通常所說(shuō)的異步操作總共有兩類(lèi):一是像文件 I/O、網(wǎng)絡(luò) I/O 這類(lèi)與 I/O 有關(guān)的操作;二是像 setTimeOut、setInterval 這類(lèi)與 I/O 無(wú)關(guān)的操作。很明顯我們所討論的異步是指與 I/O 有關(guān)的操作,即異步 I/O。

異步 I/O 的提出是期望 I/O 的調(diào)用不會(huì)阻塞后續(xù)程序的執(zhí)行,將原有等待 I/O 完成的這段時(shí)間分配給其余需要的業(yè)務(wù)去執(zhí)行。要達(dá)到這個(gè)目的,就需要用到非阻塞 I/O。

阻塞 I/O 是 CPU 在發(fā)起 I/O 調(diào)用后,會(huì)一直阻塞,等待 I/O 完成。知道了阻塞 I/O,非阻塞 I/O 就很好理解了,CPU 在發(fā)起 I/O 調(diào)用后會(huì)立即返回,而不是阻塞等待,在 I/O 完成之前,CPU 可以處理其他事務(wù)。顯然,相比于阻塞 I/O,非阻塞 I/O 多于性能的提升是很明顯的。

那么,既然使用了非阻塞 I/O,CPU 在發(fā)起 I/O 調(diào)用后可以立即返回,那它是如何知道 I/O 完成的呢?答案是輪詢(xún)。

為了及時(shí)獲取 I/O 調(diào)用的狀態(tài),CPU 會(huì)不斷重復(fù)調(diào)用 I/O 操作來(lái)確認(rèn) I/O 是否已經(jīng)完成,這種重復(fù)調(diào)用判斷操作是否完成的技術(shù)就叫做輪詢(xún)。

顯然,輪詢(xún)會(huì)讓 CPU 不斷重復(fù)地執(zhí)行狀態(tài)判斷,是對(duì) CPU 資源的浪費(fèi)。并且,輪詢(xún)的間間隔很難控制,如果間隔太長(zhǎng),I/O 操作的完成得不到及時(shí)的響應(yīng),間接降低應(yīng)用程序的響應(yīng)速度;如果間隔太短,難免會(huì)讓 CPU 花在輪詢(xún)的耗時(shí)變長(zhǎng),降低 CPU 資源的利用率。

因此,輪詢(xún)雖然滿(mǎn)足了非阻塞 I/O 不會(huì)阻塞后續(xù)程序的執(zhí)行的要求,但是對(duì)于應(yīng)用程序而言,它仍然只能算是一種同步,因?yàn)閼?yīng)用程序仍然需要等待 I/O 完全返回,依舊花費(fèi)了很多時(shí)間來(lái)等待。

我們所期望的完美的異步 I/O,應(yīng)該是應(yīng)用程序發(fā)起非阻塞調(diào)用,無(wú)須通過(guò)輪詢(xún)的方式不斷查詢(xún) I/O 調(diào)用的狀態(tài),而是可以直接處理下一個(gè)任務(wù),在 I/O 完成后通過(guò)信號(hào)量或回調(diào)將數(shù)據(jù)傳遞給應(yīng)用程序即可。

如何實(shí)現(xiàn)這種異步 I/O 呢?答案是線程池。

雖然本文一直提到,Node 是單線程執(zhí)行的,但此處的單線程是指 JavaScript 代碼是執(zhí)行在單線程上的,對(duì)于 I/O 操作這類(lèi)與主業(yè)務(wù)邏輯無(wú)關(guān)的部分,通過(guò)運(yùn)行在其他線程的方式實(shí)現(xiàn),并不會(huì)影響或阻塞主線程的運(yùn)行,反而可以提高主線程的執(zhí)行效率,實(shí)現(xiàn)異步 I/O。

通過(guò)線程池,讓主線程僅進(jìn)行 I/O 的調(diào)用,讓其他多個(gè)線程進(jìn)行阻塞 I/O 或者非阻塞 I/O 加輪詢(xún)技術(shù)完成數(shù)據(jù)獲取,再通過(guò)線程之間的通信將 I/O 得到的數(shù)據(jù)進(jìn)行傳遞,這就輕松實(shí)現(xiàn)了異步 I/O:

主線程進(jìn)行 I/O 調(diào)用,而線程池進(jìn)行 I/O 操作,完成數(shù)據(jù)的獲取,然后通過(guò)線程之間的通信將數(shù)據(jù)傳遞給主線程,即可完成一次 I/O 的調(diào)用,主線程再利用回調(diào)函數(shù),將數(shù)據(jù)暴露給用戶(hù),用戶(hù)再利用這些數(shù)據(jù)來(lái)完成業(yè)務(wù)邏輯層面的操作,這就是 Node 中一次完整的異步 I/O 流程。而對(duì)于用戶(hù)來(lái)說(shuō),不必在意底層這些繁瑣的實(shí)現(xiàn)細(xì)節(jié),只需要調(diào)用 Node 封裝好的異步 API,并傳入處理業(yè)務(wù)邏輯的回調(diào)函數(shù)即可,如下所示:

const fs = require("fs");

fs.readFile('example.js', (data) => {
  // 進(jìn)行業(yè)務(wù)邏輯的處理
});

Node 的異步底層實(shí)現(xiàn)機(jī)制在不同平臺(tái)下有所不同:Windows 下主要通過(guò) IOCP 來(lái)向系統(tǒng)內(nèi)核發(fā)送 I/O 調(diào)用和從內(nèi)核獲取已完成的 I/O 操作,配以事件循環(huán),以此完成異步 I/O 的過(guò)程;Linux 下通過(guò) epoll 實(shí)現(xiàn)這個(gè)過(guò)程;FreeBSD下通過(guò) kqueue 實(shí)現(xiàn),Solaris 下通過(guò) Event ports 實(shí)現(xiàn)。線程池在 Windows 下由內(nèi)核(IOCP)直接提供,*nix 系列則由 libuv 自行實(shí)現(xiàn)。

由于 Windows 平臺(tái)和 *nix 平臺(tái)的差異,Node 提供了 libuv 作為抽象封裝層,使得所有平臺(tái)兼容性的判斷都由這一層來(lái)完成,保證上層的 Node 與下層的自定義線程池及 IOCP 之間各自獨(dú)立。Node 在編譯期間會(huì)判斷平臺(tái)條件,選擇性編譯 unix 目錄或是 win 目錄下的源文件到目標(biāo)程序中:

以上就是 Node 對(duì)異步的實(shí)現(xiàn)。

(線程池的大小可以通過(guò)環(huán)境變量 UV_THREADPOOL_SIZE 設(shè)置,默認(rèn)值為 4,用戶(hù)可結(jié)合實(shí)際情況來(lái)調(diào)整這個(gè)值的大小。)

那么問(wèn)題來(lái)了,在得到線程池傳遞過(guò)來(lái)的數(shù)據(jù)后,主線程是如何、何時(shí)調(diào)用回調(diào)函數(shù)的呢?答案是事件循環(huán)。

基于事件循環(huán)的異步編程模型

既然使用回調(diào)函數(shù)來(lái)進(jìn)行對(duì) I/O 數(shù)據(jù)的處理,就必然涉及到何時(shí)、如何調(diào)用回調(diào)函數(shù)的問(wèn)題。在實(shí)際開(kāi)發(fā)中,往往會(huì)涉及到多個(gè)、多類(lèi)異步 I/O 調(diào)用的場(chǎng)景,如何合理安排這些異步 I/O 回調(diào)的調(diào)用,確保異步回調(diào)的有序進(jìn)行是一個(gè)難題,而且,除了異步 I/O 之外,還存在定時(shí)器這類(lèi)非 I/O 的異步調(diào)用,這類(lèi) API 實(shí)時(shí)性強(qiáng),優(yōu)先級(jí)相應(yīng)地更高,如何實(shí)現(xiàn)不同優(yōu)先級(jí)回調(diào)地調(diào)度呢?

因此,必須存在一個(gè)調(diào)度機(jī)制,對(duì)不同優(yōu)先級(jí)、不同類(lèi)型的異步任務(wù)進(jìn)行協(xié)調(diào),確保這些任務(wù)在主線程上有條不紊地運(yùn)行。與瀏覽器一樣,Node 選擇了事件循環(huán)來(lái)承擔(dān)這項(xiàng)重任。

Node 根據(jù)任務(wù)的種類(lèi)和優(yōu)先級(jí)將它們分為七類(lèi):Timers、Pending、Idle、Prepare、Poll、Check、Close。對(duì)于每類(lèi)任務(wù),都存在一個(gè)先進(jìn)先出的任務(wù)隊(duì)列來(lái)存放任務(wù)及其回調(diào)(Timers 是用小頂堆存放)。基于這七個(gè)類(lèi)型,Node 將事件循環(huán)的執(zhí)行分為如下七個(gè)階段:

timers

這個(gè)階段的執(zhí)行優(yōu)先級(jí)是最高的。

事件循環(huán)在這個(gè)階段會(huì)檢查存放定時(shí)器的數(shù)據(jù)結(jié)構(gòu)(最小堆),對(duì)其中的定時(shí)器進(jìn)行遍歷,逐個(gè)比較當(dāng)前時(shí)間和過(guò)期時(shí)間,判斷該定時(shí)器是否過(guò)期,如果過(guò)期的話,就將該定時(shí)器的回調(diào)函數(shù)取出并執(zhí)行。

pending

該階段會(huì)執(zhí)行網(wǎng)絡(luò)、IO 等異常時(shí)的回調(diào)。一些 *nix 上報(bào)的錯(cuò)誤,在這個(gè)階段會(huì)得到處理。另外,一些應(yīng)該在上輪循環(huán)的 poll 階段執(zhí)行的 I/O 回調(diào)會(huì)被推遲到這個(gè)階段執(zhí)行。

idle、prepare

這兩個(gè)階段僅在事件循環(huán)內(nèi)部使用。

poll

檢索新的 I/O 事件;執(zhí)行與 I/O 相關(guān)的回調(diào)(除了關(guān)閉回調(diào)、定時(shí)器調(diào)度的回調(diào)和 之外幾乎所有回調(diào)setImmediate());節(jié)點(diǎn)會(huì)在適當(dāng)?shù)臅r(shí)候阻塞在這里。

poll,即輪詢(xún)階段是事件循環(huán)最重要的階段,網(wǎng)絡(luò) I/O、文件 I/O 的回調(diào)都主要在這個(gè)階段被處理。該階段有兩個(gè)主要功能:

  • 計(jì)算該階段應(yīng)該阻塞和輪詢(xún) I/O 的時(shí)間。

  • 處理 I/O 隊(duì)列中的回調(diào)。

當(dāng)事件循環(huán)進(jìn)入 poll 階段并且沒(méi)有設(shè)置定時(shí)器時(shí):

  • 如果輪詢(xún)隊(duì)列不為空,則事件循環(huán)將遍歷該隊(duì)列,同步地執(zhí)行它們,直到隊(duì)列為空或達(dá)到可執(zhí)行的最大數(shù)量。

  • 如果輪詢(xún)隊(duì)列為空,則會(huì)發(fā)生另外兩種情況之一:

    • 如果有 setImmediate() 回調(diào)需要執(zhí)行,則立即結(jié)束 poll 階段,并進(jìn)入 check 階段以執(zhí)行回調(diào)。

    • 如果沒(méi)有 setImmediate() 回調(diào)需要執(zhí)行,事件循環(huán)將停留在該階段以等待回調(diào)被添加到隊(duì)列中,然后立即執(zhí)行它們。在超時(shí)時(shí)間到達(dá)前,事件循環(huán)會(huì)一直停留等待。之所以選擇停留在這里是因?yàn)?Node 主要是處理 IO 的,這樣可以更及時(shí)地響應(yīng) IO。

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

check

該階段會(huì)依次執(zhí)行 setImmediate() 的回調(diào)。

close

該階段會(huì)執(zhí)行一些關(guān)閉資源的回調(diào),如 socket.on('close', ...)。該階段晚點(diǎn)執(zhí)行也影響不大,優(yōu)先級(jí)最低。

當(dāng) Node 進(jìn)程啟動(dòng)時(shí),它會(huì)初始化事件循環(huán),執(zhí)行用戶(hù)的輸入代碼,進(jìn)行相應(yīng)異步 API 的調(diào)用、計(jì)時(shí)器的調(diào)度等等,然后開(kāi)始進(jìn)入事件循環(huán):

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

事件循環(huán)的每一輪循環(huán)(通常被稱(chēng)為 tick),會(huì)按照如上給定的優(yōu)先級(jí)順序進(jìn)入七個(gè)階段的執(zhí)行,每個(gè)階段會(huì)執(zhí)行一定數(shù)量的隊(duì)列中的回調(diào),之所以只執(zhí)行一定數(shù)量而不全部執(zhí)行完,是為了防止當(dāng)前階段執(zhí)行時(shí)間過(guò)長(zhǎng),避免下一個(gè)階段得不到執(zhí)行。

OK,以上就是事件循環(huán)的基本執(zhí)行流程?,F(xiàn)在讓我們來(lái)看另外一個(gè)問(wèn)題。

對(duì)于以下這個(gè)場(chǎng)景:

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

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

當(dāng)服務(wù)成功綁定到 8000 端口,即 listen() 成功調(diào)用時(shí),此時(shí) listening 事件的回調(diào)還沒(méi)有綁定,因此端口成功綁定后,我們所傳入的 listening 事件的回調(diào)并不會(huì)執(zhí)行。

再思考另外一個(gè)問(wèn)題,我們?cè)陂_(kāi)發(fā)中可能會(huì)有一些需求,如處理錯(cuò)誤、清理不需要的資源等等優(yōu)先級(jí)不是那么高的任務(wù),如果以同步的方式執(zhí)行這些邏輯,就會(huì)影響當(dāng)前任務(wù)的執(zhí)行效率;如果以異步的方式,比如以回調(diào)的形式傳入 setImmediate() 又無(wú)法保證它們的執(zhí)行時(shí)機(jī),實(shí)時(shí)性不高。那么要如何處理這些邏輯呢?

基于這幾個(gè)問(wèn)題,Node 參考了瀏覽器,也實(shí)現(xiàn)了一套微任務(wù)的機(jī)制。在 Node 中,除了調(diào)用 new Promise().then() 所傳入的回調(diào)函數(shù)會(huì)被封裝成微任務(wù)外,process.nextTick() 的回調(diào)也會(huì)被封裝成微任務(wù),并且后者的執(zhí)行優(yōu)先級(jí)比前者高。

有了微任務(wù)后,事件循環(huán)的執(zhí)行流程又是怎么樣的呢?換句話說(shuō),微任務(wù)的執(zhí)行時(shí)機(jī)在什么時(shí)候?

  • 在 node 11 及 11 之后的版本,一旦執(zhí)行完一個(gè)階段里的一個(gè)任務(wù)就立刻執(zhí)行微任務(wù)隊(duì)列,清空該隊(duì)列。

  • 在 node11 之前執(zhí)行完一個(gè)階段后才開(kāi)始執(zhí)行微任務(wù)。

因此,有了微任務(wù)后,事件循環(huán)的每一輪循環(huán),會(huì)先執(zhí)行 timers 階段的一個(gè)任務(wù),然后按照先后順序清空 process.nextTick()new Promise().then() 的微任務(wù)隊(duì)列,接著繼續(xù)執(zhí)行 timers 階段的下一個(gè)任務(wù)或者下一個(gè)階段,即 pending 階段的一個(gè)任務(wù),按照這樣的順序以此類(lèi)推。

利用 process.nextTick(),Node 就可以解決上面的端口綁定問(wèn)題:在 listen() 方法內(nèi)部,listening 事件的發(fā)出會(huì)被封裝成回調(diào)傳入 process.nextTick() 中,如下偽代碼所示:

function listen() {
    // 進(jìn)行監(jiān)聽(tīng)端口的操作
    ...
    // 將 `listening` 事件的發(fā)出封裝成回調(diào)傳入 `process.nextTick()` 中
    process.nextTick(() => {
        emit('listening');
    });
};

在當(dāng)前代碼執(zhí)行完畢后便會(huì)開(kāi)始執(zhí)行微任務(wù),從而發(fā)出 listening 事件,觸發(fā)該事件回調(diào)的調(diào)用。

一些注意事項(xiàng)

由于異步本身的不可預(yù)知性和復(fù)雜性,在使用 Node 提供的異步 API 的過(guò)程中,盡管我們已經(jīng)掌握了事件循環(huán)的執(zhí)行原理,但是仍可能會(huì)有一些不符合直覺(jué)或預(yù)期的現(xiàn)象產(chǎn)生。

比如定時(shí)器(setTimeout、setImmediate)的執(zhí)行順序會(huì)因?yàn)檎{(diào)用它們的上下文而有所不同。如果兩者都是從頂層上下文中調(diào)用的,那么它們的執(zhí)行時(shí)間取決于進(jìn)程或機(jī)器的性能。

我們來(lái)看以下這個(gè)例子:

setTimeout(() => {
  console.log('timeout');
}, 0);

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

以上代碼的執(zhí)行結(jié)果是什么呢?按照我們剛才對(duì)事件循環(huán)的描述,你可能會(huì)有這樣的答案:由于 timers 階段會(huì)比 check 階段先執(zhí)行,因此 setTimeout() 的回調(diào)會(huì)先執(zhí)行,然后再執(zhí)行 setImmediate() 的回調(diào)。

實(shí)際上,這段代碼的輸出結(jié)果是不確定的,可能先輸出 timeout,也可能先輸出 immediate。這是因?yàn)檫@兩個(gè)定時(shí)器都是在全局上下文中調(diào)用的,當(dāng)事件循環(huán)開(kāi)始運(yùn)行并執(zhí)行到 timers 階段時(shí),當(dāng)前時(shí)間可能大于 1 ms,也可能不足 1 ms,具體取決于機(jī)器的執(zhí)行性能,因此 setTimeout() 在第一個(gè) timers 階段是否會(huì)被執(zhí)行實(shí)際上是不確定的,因此才會(huì)出現(xiàn)不同的輸出結(jié)果。

(當(dāng) delaysetTimeout 的第二個(gè)參數(shù))的值大于 2147483647 或小于 1 時(shí), delay 會(huì)被設(shè)置為 1。)

我們接著看下面這段代碼:

const fs = require('fs');

fs.readFile(__filename, () => {
  setTimeout(() => {
    console.log('timeout');
  }, 0);
  setImmediate(() => {
    console.log('immediate');
  });
});

可以看到,在這段代碼中兩個(gè)定時(shí)器都被封裝成回調(diào)函數(shù)傳入 readFile 中,很明顯當(dāng)該回調(diào)被調(diào)用時(shí)當(dāng)前時(shí)間肯定大于 1 ms 了,所以 setTimeout 的回調(diào)會(huì)比 setImmediate 的回調(diào)先得到調(diào)用,因此打印結(jié)果為:timeout immediate。

以上是在使用 Node 時(shí)需要注意的與定時(shí)器相關(guān)的事項(xiàng)。除此之外,還需注意 process.nextTick()new Promise().then() 還有 setImmediate() 的執(zhí)行順序,由于這部分比較簡(jiǎn)單,前面已經(jīng)提到過(guò),就不再贅述了。

總結(jié)

文章開(kāi)篇從為什么要異步、如何實(shí)現(xiàn)異步兩個(gè)角度出發(fā),較詳細(xì)地闡述了 Node 事件循環(huán)的實(shí)現(xiàn)原理,并提到一些需要注意的相關(guān)事項(xiàng),希望對(duì)你有所幫助。

如果覺(jué)得這篇文章寫(xiě)的不錯(cuò)的話,就請(qǐng)給我點(diǎn)個(gè)贊吧!

參考資料

到此這篇關(guān)于Node異步和事件循環(huán)的文章就介紹到這了,更多相關(guān)Node異步和事件循環(huán)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Express + Node.js實(shí)現(xiàn)登錄攔截器的實(shí)例代碼

    Express + Node.js實(shí)現(xiàn)登錄攔截器的實(shí)例代碼

    本篇文章主要介紹了Express + Node.js實(shí)現(xiàn)攔截器的實(shí)例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-07-07
  • WebSocket實(shí)現(xiàn)簡(jiǎn)單客服聊天系統(tǒng)

    WebSocket實(shí)現(xiàn)簡(jiǎn)單客服聊天系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了WebSocket實(shí)現(xiàn)簡(jiǎn)單客服聊天系統(tǒng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • 快速掌握Node.js模塊封裝及使用

    快速掌握Node.js模塊封裝及使用

    這篇文章主要為大家詳細(xì)介紹了Node.js模塊封裝及使用,幫助大家快速掌握Node.js模塊封裝及使用,感興趣的小伙伴們可以參考一下
    2016-03-03
  • module.exports和exports使用誤區(qū)案例分析

    module.exports和exports使用誤區(qū)案例分析

    module.exports和exports使用誤區(qū),使用require()模塊時(shí),得到的永遠(yuǎn)都是module.exports指向的對(duì)象
    2023-04-04
  • window系統(tǒng) nodejs安裝opencv環(huán)境配置圖文詳解

    window系統(tǒng) nodejs安裝opencv環(huán)境配置圖文詳解

    這篇文章主要介紹了window系統(tǒng) nodejs安裝opencv環(huán)境配置,結(jié)合圖文形式詳細(xì)分析了window環(huán)境下 nodejs安裝opencv的具體步驟、注意事項(xiàng)
    2023-04-04
  • 使用Node.js實(shí)現(xiàn)一個(gè)多人游戲服務(wù)器引擎

    使用Node.js實(shí)現(xiàn)一個(gè)多人游戲服務(wù)器引擎

    這篇文章主要給大家介紹了關(guān)于如何使用Node.js實(shí)現(xiàn)一個(gè)多人游戲服務(wù)器引擎的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者使用Node.js具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • 究竟什么是Node.js?Node.js有什么好處?

    究竟什么是Node.js?Node.js有什么好處?

    這篇文章主要介紹了究竟什么是Node.js?Node.js有什么好處?,為試圖解釋什么是 Node.js,本文將簡(jiǎn)要介紹一些背景信息:它要解決的問(wèn)題,它如何工作,如何運(yùn)行一個(gè)簡(jiǎn)單應(yīng)用程序,最后,Node 在什么情況下是一個(gè)好的解決方案,需要的朋友可以參考下
    2015-05-05
  • 為何從eggjs升級(jí)到midwayjs的原因詳解

    為何從eggjs升級(jí)到midwayjs的原因詳解

    這篇文章主要為大家介紹了為何從eggjs升級(jí)到midwayjs的原因詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • NodeJs操作MongoDB教程之分頁(yè)功能以及常見(jiàn)問(wèn)題

    NodeJs操作MongoDB教程之分頁(yè)功能以及常見(jiàn)問(wèn)題

    這篇文章主要給大家介紹了關(guān)于NodeJs操作MongoDB教程之分頁(yè)功能以及常見(jiàn)問(wèn)題的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用NodeJs具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • 使用node.js 制作網(wǎng)站前臺(tái)后臺(tái)

    使用node.js 制作網(wǎng)站前臺(tái)后臺(tái)

    本文給大家介紹實(shí)用node.js 制作網(wǎng)站前臺(tái)和后臺(tái),非常的詳盡,有需要的朋友可以參考下
    2014-11-11

最新評(píng)論