Node.js學習筆記(2)——關於非同步編程風格
Node.js的非同步編程風格是它的一大特點,在代碼中就是體現在回調中。 首先是代碼的順序執行: function heavyCompute(n, callback) { var count = 0, i, j; for (i = n; i > 0; --i) { for (j = n; j > 0; --j) { count += 1; } }callback(count); } heavyCompute(10000, function (count) { console.log(count); }); console.log('hello'); 這裡輸出100000000 hello,這個說明同一時間內只能執行一個函數,即使要花費多長時間,一個一個來。 但是,有兩個有趣的例子: 1、 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,一點都不含糊。<未完待續>