標籤:
非同步編程
node.js 編程的直接體現就是回調,非同步編程依託於回調來實現: node使用了大量的回呼函數,所有API都支援回呼函數 。如讀取檔案等。
這裡對不懂線程和非同步和同步的稍微解釋下這三個名詞 。
線程 : 簡單的說就是做一件事 . 即執行一段程式碼 。js引擎就是一個單線程 的 處理 方式 .單線程是說 同一時間只能做一件事 。
同步 :就是這件事必須要先做完前面的才能做後面的,否則後面的無法完成. 這就像我們的js代碼會從上往下 運行 .
非同步 :簡單的說就是兩個線程,你做你的,我做我的,相互並不影響。
並發 :就是 說多個非同步線程同時運行, 所以 這種情況 處理效果最高 ,也是我們大多 數時候的處理方式 。
同步的情況下,這件事必須從上 往 下 , 當然 也可以是兩個線程, 但這兩個線程 必須前一個做完才能執行下一個 .
如 :function fun(){
var x=1; //先運行 此行
var y=1;//再運行此行
consoel.log(x+y);//最後運行此行
}
fun(); //調用 fun函數
非同步情況下 , 大家各幹各的,說不準說先做完 誰後做完 .
如 : console.log("12221");
setTimeout(function(){
console.log("111");
},1000);
console.log("13331");
這個定時器,setTimeout會開啟一個非同步線程,等一秒後再執行回呼函數裡的代碼 .並不行阻塞 13331 的輸出執行 .
當然這裡還有一個非同步並發安全的問題,即是說當兩個非同步線程 同時做一件事時 就會產生非同步並發的安全問題 .
node 回呼函數
好了,這裡繼續講 node 的 回呼函數。
下面以 阻塞代碼和非阻塞代碼為例 :
阻塞代碼 : var fs=require("fs"); // 擷取fs模組 即檔案讀模數塊
var data=fs.readFileSync("input.txt");//讀取input.txt 檔案 檔案內容是 菜鳥教程官網地址:www.runoob.com
console.log(data.toString());
console.log("程式執行結束");
執行 :檔案存放 在 D:\softSetting\node\a 檔案夾下 ,所以 : 執行代碼如下
下面再來個非阻塞的讀取檔案的例子:
同樣的 D:\softSetting\node\a 檔案夾下 建立 main2.js
var fs=require("fs");
fs.readFile("input.txt",function(err,data){
if(err){ return console.error(err);}
console.log(data.toString());
});
console.log("程式執行結束");
執行 :
node 的回呼函數 是這樣的:function(err,data){ }
err 表示 錯誤 ,當 回呼函數 執行 出錯時 自動出現err 內容 , data表示回呼函數接收資料 。
node 事件迴圈 -這個比較難
node.js 是單進程單線程應用程式,但是通過事件和回調支援並發,所以效能非常高
node.js 的每一個 API 都是非同步,並作為一個獨立線程運行,使用非同步函數調用,並處理並發。
node.js 基本上所有的事件機制都是用設計模式中觀察者模式實現。這個下一章單獨講 。
node.js 單線程類似進入一個while(true) 的事件迴圈,直到沒有事件觀察者退出,每個非同步事件都產生一個事件觀察者,如果有事件發生就調用該回呼函數。
以上是node 事件迴圈的基本模型,也被稱為非阻塞式IO或事件驅動IO , webserver 一直接受請求而不等待任何讀寫操作,EventEmitter 綁定事件on並監聽事件(Event) .
在事件驅動模型中,會產生一個主迴圈Event Loop聽事件,當檢測到事件時觸發回呼函數 Event Handlers .
EventEmitter 補充 :
node.js 回呼函數、事件迴圈、EventEmitter ar