node.js入門 - 5.事件循環機制(event loop)


  今天要介紹的是node的事件循環機制,他是一些交互系統的基本概念,他更是javascript語言核心的一部分。因為對於使用瀏覽器的用戶,javascript就是通過處理用戶的click,mouse等相關的事件來處理用戶的請求的。對於像node這樣的服務器來說,事件循環也同樣起到相當重要的作用,比如用來處理來自客戶端的request請求。下面我們就對node的事件循環做個簡單的介紹。

  node采用單線程的處理機制,對所有的I/O請求采用非堵塞的工作方式。也就是說,對於http的請求,數據查詢,文件的I/O等其他操作,系統不會堵塞當前線程而去等待他直到他返回結果;相反的,他們會立即執行當前請求,發送一個處理當前請求結果的回調事件,然后接着處理新的請求。當之前的回調函數返回結果的時候,輸出結果。這也就意味着,在node中存在着大量回調函數用於處理不同請求。回調函數又經常以級聯的方式初始化其他的回調函數,這與瀏覽器的處理方式是相當不同的。node缺乏並發性,他只會使用服務器上的一個cpu,而不是多個。使用多個cpu的問題在於,需要不斷的協調多個cpu之間的運行,這就帶來了不同cpu之間的通信,交換彼此的狀態信息,這是一種比較復雜的處理模式。而node使用單線程的方式回避了這一問題。node的這種處理機制更為高效,下面我們舉個例子來說明。

  假設我們要去快餐店吃飯,有兩種不同服務模式的快餐店,一種是基於事件驅動的(我們的node服務器),一種不是(像iis,apache)。對於傳統的服務器,在接收到你的請求之后,直到他完成你的請求,否則他不會去接待下一個用戶。當服務員輸入你的訂單之后還有很多事情要做,處理你的支付,幫你倒水,還有一段時間(不確定時長)去等待廚房准備好你的漢堡。服務員(相當於服務器上的線程)每次只能接待一位顧客,直到完成當前顧客的接待之后,才會去接待下一位顧客。很顯然,這種方式效率不高,他浪費了太多的時間在等待廚房做漢堡的工作上。而現實中的快餐店采用的是另外一種模式,當接收到你的訂單之后,他會給你一個號碼牌,這個號碼牌就相當於回調函數。接着他會去接待下一位顧客。當你的訂餐准備好之后,服務員會呼叫你的號碼叫你來取餐。這就是node采用的模式,看得出他要高效的多。

  

  node不太適用單個請求處理時間比較長的場景;適用於並發比較多,每個請求所需處理時間比較短的場景。我們來看一個例子:

EE = require('events').EventEmitter;
ee = new EE();
die = false;
ee.on('die', function() {   die = true; }); setTimeout(function() {   ee.emit('die'); }, 100);
while(!die) { }
console.log('done');

  你可以猜猜‘done’會不會輸出。答案是明顯的,node根本沒有機會回調timeout方法,程序會堵塞在while循環處。你也可以執行一個瀏覽器的版本:

var die = false;

setTimeout(function() {
  die=true
}, 100);

while(!die) {
}

alert('done');

  瀏覽器也同樣不會彈出‘done’。這個簡單的例子可以很好的解釋javascript的單線程執行,javascript只有把當前手頭上的事情處理完畢之后,才會去做別的事情。就像上面的例子,javascript會一直專心處理while處的代碼,根本沒有機會去執行timeout的方法。這也解釋了為什么node不適用於處理單個請求時間比較長的場景(例如,處理回調函數返回內容需要很長的時間)。因為在處理完當前請求之前,node沒有機會去接待下一個請求,處理別的請求的回調,這會直接影響其他用戶的體驗。

   

  開發node程序,有兩條建議:

1.一旦代碼的初始化工作完成后,就激活事件;

2.如果遇到比較耗時的操作,可以考慮把他委托給web worker去執行。

 

參考資料:

http://www.infoq.com/cn/articles/what-is-nodejs

http://www.nodebeginner.org/index-zh-cn.html

http://baike.baidu.com/view/3974030.htm?subLemmaId=3974030&fromenter=nodejs

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM