摘要:實際上官方給出的單線程是具有誤導(dǎo)性的。如果開發(fā)者在回調(diào)函數(shù)中調(diào)用了阻塞方法比如上文中的函數(shù),那么整個事件輪詢就會阻塞,事件隊列中的事件得不到及時處理。后記參考文章事件輪詢詳述
前言
總括 :
原文地址:理解Node.js的事件輪詢
Node小應(yīng)用:Node-sample
智者閱讀群書,亦閱歷人生
正文 Node.js的兩個基本概念Node.js的第一個基本概念就是I/O操作開銷是巨大的:
所以,當(dāng)前變成技術(shù)中最大的浪費來自于等待I/O操作的完成。有幾種方法可以解決性能的影響:
同步方式:按次序一個一個的處理請求。利:簡單;弊:任何一個請求都可以阻塞其他所有請求。
開啟新進(jìn)程:每個請求都開啟一個新進(jìn)程。利:簡單;弊:大量的鏈接意味著大量的進(jìn)程。
開啟新線程:每個請求都開啟一個新線程。利:簡單,而且跟進(jìn)程比,對系統(tǒng)內(nèi)核更加友好,因為線程比進(jìn)程輕的多;弊:不是所有的機器都支持線程,而且對于要處理共享資源的情況,多線程編程會很快變得太過于復(fù)雜。
第二個基本概念是每個連接都創(chuàng)建一個新線程是很消耗內(nèi)存的(例如:你可以對比Nginx回想一下Apache內(nèi)存耗盡的情景)。
Apache是多線程的:它為每個請求開啟一個新的線程(或者是進(jìn)程,這取決于你的配置),當(dāng)并發(fā)連接增多時,你可以看看它是怎么一點一點耗盡內(nèi)存的。Nginx和Node.js不是多線程的,因為線程的消耗太“重”了。它們兩個是單線程、基于事件的,這就把處理眾多連接所產(chǎn)生的線程/進(jìn)程消耗給消除了。
單線程確實只有一個線程:你不能并行執(zhí)行任何代碼,比如:下面的“sleep”將會阻塞sever1秒鐘:
function sleep() { var now = new Data().getTime(); while (new Date().getTime() < now + 1000) { // do nothing } } sleep();
但就我目前學(xué)習(xí)階段而言,我覺得好多人對于所謂的node單線程是有誤解的。實際上官方給出的“單線程”是具有誤導(dǎo)性的。所謂的單線程是指你的代碼只運行在一個線程上(好多地方都叫它主線程,實際上Javascript的瀏覽器運行環(huán)境不也是這么處理我們寫的Javascript代碼的嘛),而諸多任務(wù)的并行處理,就需要多線程了,如下圖:
如上圖,Node.js中的單線程之說指的就是這個主線程,這個主線程有一個循環(huán)結(jié)構(gòu),保持著整個程序(你寫的代碼)的運轉(zhuǎn)。
事件輪詢其實上面我們所說的維持主線程運行的循環(huán)這部分就是"事件輪詢",它存在于主線程中,負(fù)責(zé)不停地調(diào)用開發(fā)者編寫的代碼。但對開發(fā)者是不可見的。so...開發(fā)者編寫的代碼是怎樣被調(diào)用的呢?看下圖:
如上圖,異步函數(shù)在執(zhí)行結(jié)束后,會在事件隊列中添加一個事件(遵循先進(jìn)先出原則),主線程中的代碼執(zhí)行完畢后(即一次循環(huán)結(jié)束),下一次循環(huán)開始就在事件隊列中"讀取"事件,然后調(diào)用它所對應(yīng)的回調(diào)函數(shù)(所以回調(diào)函數(shù)的執(zhí)行順序是不一定的)。如果開發(fā)者在回調(diào)函數(shù)中調(diào)用了阻塞方法(比如上文中的sleep函數(shù)),那么整個事件輪詢就會阻塞,事件隊列中的事件得不到及時處理。正因為這樣,nodejs中的一些庫方法均是異步的,也提倡用戶調(diào)用異步方法。
var fs = require("fs"); fs.readFile("hello.txt", function (err, data) { //異步讀取文件 console.log("read file end"); }); while(1) { console.log("call readFile over"); }
如上代碼,我們雖然使用了異步方法readfile讀取文件,但read file end永遠(yuǎn)不會輸出,因為代碼始終在while循環(huán)中,下一次事件輪詢始終沒法開始,也就沒法"讀取"事件隊列調(diào)用相應(yīng)的回調(diào)函數(shù)了。
最后有一個Node-sample是博主平時積累的一些代碼,包含注釋,匯總成了一個小應(yīng)用,還是可以看到學(xué)習(xí)的蛛絲馬跡的。感興趣的您可以看看。
后記參考文章:
Understanding the node.js event loop
nodejs事件輪詢詳述
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/86777.html
摘要:定時器階段這個是事件循環(huán)開始的階段,綁定到這個階段的隊列,保留著定時器的回調(diào),盡管它并沒有將回調(diào)推入隊列中,但是以最小的堆來維持計時器并且在到達(dá)規(guī)定的事件后執(zhí)行回調(diào)。 本文,將會詳細(xì)的講解 node.js 事件循環(huán)工作流程和生命周期 一些常見的誤解 在 js 引擎內(nèi)部的事件循環(huán) 最常見的誤解之一,事件循環(huán)是 Javascript 引擎(V8,spiderMonkey等)的一部分。事實上...
摘要:檢索新的事件執(zhí)行與相關(guān)的回調(diào)幾乎所有,除了由定時器調(diào)度的一些和將在適當(dāng)?shù)臅r候在這里阻塞。在事件循環(huán)的每次運行之間,檢查它是否在等待任何異步或定時器,如果沒有,則徹底關(guān)閉。 Node.js事件循環(huán)、定時器和process.nextTick() 什么是事件循環(huán)? 事件循環(huán)允許Node.js執(zhí)行非阻塞I/O操作 — 盡管JavaScript是單線程的 — 通過盡可能將操作卸載到系統(tǒng)內(nèi)核。 ...
摘要:回調(diào)函數(shù)執(zhí)行幾乎所有的回調(diào)函數(shù),除了關(guān)閉回調(diào)函數(shù),定時器計劃的回調(diào)函數(shù)和。輪詢此階段有兩個主要的功能執(zhí)行已過時的定時器腳本處理輪詢隊列中的事件。一旦輪詢隊列為空,事件循環(huán)將檢查已達(dá)到時間閾值的定時器。 什么是事件循環(huán)(Event Loop)? 事件環(huán)使得Node.js可以執(zhí)行非阻塞I/O 操作,只要有可能就將操作卸載到系統(tǒng)內(nèi)核,盡管JavaScript是單線程的。 由于大多數(shù)現(xiàn)代(終端...
摘要:的單線程,與它的用途有關(guān)。特點的顯著特點異步機制事件驅(qū)動。隊列的讀取輪詢線程,事件的消費者,的主角。它將不同的任務(wù)分配給不同的線程,形成一個事件循環(huán),以異步的方式將任務(wù)的執(zhí)行結(jié)果返回給引擎。 這兩天跟同事同事討論遇到的一個問題,js中的event loop,引出了chrome與node中運行具有setTimeout和Promise的程序時候執(zhí)行結(jié)果不一樣的問題,從而引出了Nodejs的...
摘要:如果當(dāng)前沒有事件也沒有定時器事件,則返回。相關(guān)資料關(guān)于的架構(gòu)及設(shè)計思路的事件討論了使用線程池異步運行代碼。下一篇初窺事件機制的實現(xiàn)二中定時器的實現(xiàn) 在瀏覽器中,事件作為一個極為重要的機制,給予JavaScript響應(yīng)用戶操作與DOM變化的能力;在Node.js中,事件驅(qū)動模型則是其高并發(fā)能力的基礎(chǔ)。 學(xué)習(xí)JavaScript也需要了解它的運行平臺,為了更好的理解JavaScript的事...
閱讀 2361·2021-11-15 11:37
閱讀 3048·2021-09-01 10:41
閱讀 882·2019-12-27 11:58
閱讀 802·2019-08-30 15:54
閱讀 775·2019-08-30 13:52
閱讀 2987·2019-08-29 12:22
閱讀 1137·2019-08-28 18:27
閱讀 1532·2019-08-26 18:42