-
事件循環(huán)(event loop)
js是單線程語言,這是由于設計者最初設計的時候,考慮到其只運行在瀏覽器端,不應該太復雜霸褒。
事件循環(huán)有兩個重要部分:1.事件 2.事件的訂閱者,也就是事件處理器妙蔗。
一個Nodejs程序運行后,事件循環(huán)就會一直存在疆瑰,拋出事件眉反,直到程序結束運行。事件循環(huán)需借助操作系統(tǒng)進行實現(xiàn)穆役,如select寸五、epoll、kqueue耿币、IOCP梳杏;Nodejs是對系統(tǒng)進行了進一步的封裝(libuv)。
Paste_Image.png
什么是 Event Loop淹接?
[譯]事件循環(huán)十性,Node.js背后的核心概念 setImmediate VS process.nextTick VS setTimeout(fn, 0)
- process.nextTick: 回調函數(shù)會被放入數(shù)組中,而且在下一次事件循環(huán)前一起執(zhí)行塑悼;
- setImmediate: 回調函數(shù)放入鏈表中劲适,下次循環(huán)結束后從鏈表中取出一個執(zhí)行。
- setTimeout(fn, 0): 通過源碼可知厢蒜,它是按照setTimeout(fn, 1)執(zhí)行的霞势,因此如果一個時間循環(huán)的時間小于1ms烹植,那么setImmediate在前,否則setTimeout(fn, 0)在前愕贡。 但是考慮到setTimeout(fn, 0)的性能問題草雕,Node作者推薦采用setImmediate。
三者中process.nextTick的優(yōu)先級最高固以,其次是setTimeout墩虹,但是這并不一定代表執(zhí)行順序。由于setTimeout采用紅黑樹實現(xiàn)嘴纺,setImmediate采用鏈表實現(xiàn)败晴;對比效率而言,Node中推薦采用setImmediate栽渴。
setImmediate vs nextTick vs setTimeout(fn, 0)
全局對象
Node的全局對象是global尖坤,瀏覽器中的全局變量是window,可以根據(jù)這個區(qū)分js是運行在瀏覽器中還是Node中闲擦。
在瀏覽器中慢味,var定義的變量會掛載到window下,因此:var x=1; window.x==1 //true
墅冷;
在Node中纯路,var定義的變量并不會掛載到global下,因此:var x=1; global.x==1 //false
寞忿。
Node還提供了process
驰唬、console
、setTimeout
等全局的對象或者方法腔彰。exports
和module.exports
的區(qū)別
Nodje的輸出是module.exports
叫编。module.exports
默認是一個空對象{}
,exports
是指向其的引用霹抛。舉個例子:
var aa = {};
var bb = aa; // bb就是aa的引用
bb.cc = 1;
aa.cc == 1 // true
aa = {dd:1}
bb.dd == 1 // false undefined
類似上述的例子去理解兩者的區(qū)別:
```
// b.js 輸出一個函數(shù)搓逾,改變了module.exports的默認值{},此時exports和module.exports不再指向同一個對象
module.exports = function (name, age) {
// exports = module.exports = function (name, age) { // 此時兩者還是指向同一個對象
this.name = name;
this.age = age;
}
exports.sex = "male";
var Person = require("./b");
var person = new Person("Tony", 33);
console.log(person); // {name:"Tony", age:33}
console.log(Person.sex); // undefined
```
- 模塊機制
模塊優(yōu)先從緩存中加載杯拐,模塊分析按照.js
霞篡、.json
、.node
擴展名進行端逼。
三種類型的模塊: - 核心模塊朗兵,如
http
,fs
。 -
.
顶滩、..
矛市、/
等相對或絕對路徑的文件模塊。 - 非路徑形式的文件模塊诲祸,如從npm下載到本地的模塊浊吏。
第3種模塊而昨,系統(tǒng)會迭代遍歷當前目錄或者父目錄的node-modules
文件夾進行查找。如果找到的不是一個文件找田,而是一個文件夾歌憨,那么系統(tǒng)會解析文件夾的package.json
文件進行分析。
- uncaughtException
異常處理可以通過try...catch進行捕獲墩衙;但是如果try中的異常是異步的务嫡,并不會被catch到:
try{
process.nextTick(function my_app(){
throw new Error('Catch me');
})
}catch(e){
// never called
}
異常沒有被捕獲到,就會通過事件冒泡最終觸發(fā)uncaughtException事件漆改。有uncaughtException時心铃,服務會觸發(fā)exist事件,造成進程退出挫剑。如果想監(jiān)聽uncaughtException處理服務的全局異常去扣,可能會造成服務超時;進一步造成內存泄露和服務的不穩(wěn)定樊破。
比較好的處理方式是:借助cluster模式愉棱,針對異常返回一個錯誤碼,然后重啟該wordker實例哲戚。
NodeJS 異常處理 uncaughtException 篇
Node.js 異步異常的處理與domain模塊解析