JavaScript,Node.js 巢狀非同步呼叫的實現以及注意點
阿新 • • 發佈:2019-02-10
前言
使用Node.js實現伺服器端時,需要處理不少的非同步請求。
有些時候,我們會遇到這種情況:
對於某個數組裡面的字串,你需要依次地通過非同步呼叫的方法向資料庫請求資料,即,我先用第一個字串提交請求,然後在回撥函式中用第二個字串提交請求,以此類推,我們就要像這樣呼叫程式碼,即:
/*
*假設有非同步函式非同步傳回
A(para, callback){
...
得到結果result
...
callback(result);
}
我們要對如下字串陣列的每一項呼叫A
data[]
*/
A(data[0], function(result1){
//處理result1
A(data[1], function(result2){
//處理result2
......
});
});
然而很多時候,我們對於result的處理是相同的,而且寫多層巢狀實在是不美觀,且工作量巨大。
此時我們就可以用一個迴圈來實現函式的巢狀。
思路
我們需要指定一個函式陣列fun_list[],並讓每個函式都長成下面這樣
fun_list[i] = function(){
A(data[i], function(result){
/*處理result*/
fun_list[i+1](); //呼叫下一個函式陣列中的函式
//最後一個函式就不用往下呼叫了
});
}
這樣,我們只要呼叫fun_list[0]();
就可以實現巢狀非同步呼叫。
很容易想到通過一個迴圈來實現這個陣列,就像下面這樣:
for(var i = 0; i < data.length;i++){
fun_list.push(function(){
A(data[i], function(result){
/*處理result*/
fun_list[i+1 ]();
});
});
}
fun_list.push(function(){
/*不做處理,或者做陣列處理完成之後的工作*/
});
fun_list[0]();
看到這裡,興奮地去嘗試上述程式碼,你會發現,直接就報錯了。
JavaScript的特性
造成問題的原因是,函式陣列中的i,並不是一個常量,而是一個變數i。也就是說,在迴圈完成時,所有的i都會變成data.length,而data[data.length]是沒定義的,所以就報錯了。
這個也是JavaScript的一個小特性,為了支援非同步,傳入的i是一個變數,而即使出了for迴圈,這個i仍舊是存在的。所以我們作出一點小修改,將變數變成一個常量。
修改
我們可以在呼叫function時傳入,這個是第幾個function,對於這個傳入值,則是每個函式都是唯一的,程式碼修改如下:
for(var i = 0; i < data.length;i++){
fun_list.push(function(j){
A(data[j], function(result){
/*處理result*/
fun_list[j+1](j+1);
});
});
}
fun_list.push(function(j){
/*不做處理,或者做陣列處理完成之後的工作*/
});
fun_list[0](0);
經過這番修改,就能夠實現巢狀非同步呼叫了。