前一天我們看了簡單建立服務伺服器的方法,其中我們稍微的有提到事件驅動與callback()函數,今天在正式開始之前,我們先來聊聊一個在Coding NodeJS時常會犯下的錯誤。
我們先來看看底下這段程式碼
function factorialOperate(num, callback, tmpRS) {
var rs = 0;
if (!tmpRS) {
rs = num * (num - 1);
} else {
rs = (num - 1) * tmpRS;
}
if (num - 1 > 1) {
factorialOperate(num - 1, callback, rs);
} else {
return callback(rs);
}
}
exports.factorialOperate = factorialOperate;
我們透過callback()做了一個用來計算階層的函數,這個函數其實可以簡單地透過for迴圈就可以達成,但由於示範的需求,於此把它寫成具有callback()型態的函數。
接著我們在寫一個主程式來呼叫此函數進行運算,大致內容大概像下方這樣:
function noTimeout() {
var num1 = 10;
var num2 = 5;
var rs1 = 0;
var rs2 = 0;
var result = 0;
console.log('===========No Timeout Start===========');
factorialOperate(num1, function(rs){
rs1 = rs;
console.log(num1 + '! = ' + rs1);
});
factorialOperate(num2, function(rs){
rs2 = rs;
console.log(num2 + '! = ' + rs2);
});
result = rs1 + rs2;
console.log(result);
console.log('===========No Timeout End===========');
}
執行的結果畫面為下圖所示:
這執行結果看起來非常完美,沒有什麼不對。但記得,Node JS主要是作用於網路服務的程序,我們必須考慮到當大量演算,或網路傳輸延遲時會發生時,會發生怎樣的情況。
為此我們另外新增一個具有callback()的函數,並在其中加入了set timeout 100毫秒來模擬大量運算或網路延遲下的結果。
function factorialOperateWithTimeout(num, callback, tmpRS) {
var rs = 0;
if (!tmpRS) {
rs = num * (num - 1);
} else {
rs = (num - 1) * tmpRS;
}
if (num - 1 > 1) {
setTimeout(function() {
factorialOperateWithTimeout(num - 1, callback, rs);
}, 100);
} else {
return callback(rs);
}
}
exports.factorialOperateWithTimeout = factorialOperateWithTimeout;
同樣的也寫一個主程序來呼叫此函數進行運算,大致內容大概像下方這樣:
function withTimeout() {
var num1 = 10;
var num2 = 5;
var rs1 = 0;
var rs2 = 0;
var result = 0;
console.log('===========With Timeout 100ms Start===========');
factorialOperateWithTimeout(num1, function(rs){
rs1 = rs;
console.log(num1 + '! = ' + rs1);
});
factorialOperateWithTimeout(num2, function(rs){
rs2 = rs;
console.log(num2 + '! = ' + rs2);
});
result = rs1 + rs2;
console.log(result);
console.log('===========With Timeout 100ms End===========');
}
由圖中可以發現主控台所輸出的訊息好像不是我們想要的結果!?看起來似乎我們Set Timeout 100毫秒來模擬延遲效果,造成運算出來的結果順序不一,那到底該怎麼修正這種情況呢?
function useCallBack() {
var num1 = 10;
var num2 = 5;
var rs1 = 0;
var rs2 = 0
var result = 0;
console.log('===========use Callback Start===========');
factorialOperateWithTimeout(num1, function(rs){
rs1 = rs;
console.log(num1 + '! = ' + rs1);
factorialOperateWithTimeout(num2, function(rs){
rs2 = rs;
console.log(num2 + '! = ' + rs2);
result = rs1 + rs2;
console.log(result);
console.log('===========use Callback End===========');
});
});
}
其實非常簡單,只要運用callback的方式,來把兩個 "factorialOperateWithTimeout()"呼叫語句串起來就好了,如上段程式碼內容所示。而執行結果就會像下圖一樣,達到我們想要的目標。
也許有朋友會問,那如果我們想要呼叫多個函數,並把這些函數的傳回結果相互交叉運算時,豈不是要在callback()裡面加上callback()?這樣call來call去,不會讓程式碼不好判讀,也很容易造成自己在開發時的混淆狀況嗎?
的確是如此... 所以在開發之前,可能就必須想好每個function之間的因果關係。但其實也不用這麼的緊張,明天讓我們來介紹一個好用的套件"async",到時讓我們來看看如何使用async來簡單的達到運算同步的需求。
文章標籤
全站熱搜
