Node.js的異步編程風格是它的一大特色,在代碼中就是體如今回調中。node
首先是代碼的順序執行:編程
function heavyCompute(n, callback) {異步
var count = 0,異步編程
i, j;函數
for (i = n; i > 0; --i) {測試
for (j = n; j > 0; --j) {spa
count += 1; }線程
}callback(count);code
}進程
heavyCompute(10000, function (count) {
console.log(count);
});
console.log('hello');
這裏輸出100000000 hello,這個說明同一時間內只能執行一個函數,即便要花費多長時間,一個一個來。
可是,有兩個有趣的例子:
一、
setTimeout(function () {
console.log('world');
}, 1000);
console.log('hello');
輸出helloworld,咱們能夠這樣理解,順序執行的線程中,只要有一個函數設置了timeout以後,就會當即建立一個平行線程立馬返回,而後讓js主線程接着去執行後面的代碼,在收到這個平行線程的通知以後,再執行回調函數。結果就是helloworld而不是在等待1s以後幾乎同時出現worldhello。
2,下面這種狀況就是很典型的一種:
function heavyCompute(n) {
var count = 0, i, j;
for (i = n; i > 0; --i) {
for (j = n; j > 0; --j) {
count += 1;
}
}
}
var t = new Date();
setTimeout(function () {
console.log(new Date() - t);
}, 1000);
heavyCompute(50000);
在執行到setTimeout函數(或者setInterval
這些常見的,這類函數還包括NodeJS提供的諸如fs.readFile
之類的異步API。)的時候,看到有1000毫秒的延時設置,因而建立了一個平行線程以後立馬去執行後面的代碼,可是後面的代碼花費的時間更多,因而你們一塊兒等着後面的代碼執行完畢、輸出結果,再去執行原來的平行線程,而這個平行線程還要花費一秒以上。
爲了驗證平行線程裏面的代碼在node執行後面代碼的時候有沒有在後臺偷偷執行,我就測試瞭如下代碼:
function heavyCompute(n) {
var count = 0, i, j;
for (i = n; i > 0; --i) {
for (j = n; j > 0; --j) {
count += 1;
}
}
}
var t = new Date();
setTimeout(function () {
heavyCompute(50000);//經過對這句話的註釋與否,經過比較時間之間的差值,咱們就能夠看出來平行線程到底有沒有平行執行
console.log(new Date() - t);
}, 1000);
var t1 = new Date();
heavyCompute(50000);
console.log('a');
console.log(new Date() - t1);
結果證實,建立平行進程以後,誰也沒有動它。
總結一下,js是單線程執行的,即便平行線程裏面的函數執行完畢以後,回調函數也要等主線程執行完畢空閒的時候才能開始執行;
咱們仍然回到JS是單線程運行的這個事實上,這決定了JS在執行完一段代碼以前沒法執行包括回調函數在內的別的代碼。
這個結論很重要,換句話說,node在同一時間內永遠只能執行一段代碼,碰到了settimeout這樣的函數以後立馬生成一個平行線程,而後就把這個平行線程放在那裏不動繼續去執行後面的函數,後面的函數執行完畢、主線程空閒以後,再回來從頭執行這個平行線程以內的代碼,這是一個專注的node.js,一點都不含糊。<未完待續>