2012-03-30 92 views
9

我有一個節點應用程序,它是而不是一個web應用程序 - 它在返回1之前完成了一系列異步任務。緊接在返回之前,程序的結果被打印到控制檯。如何編寫一個node.js函數,等待事件在'返回'之前觸發?

如何確保在返回之前完成所有異步工作?通過在調用res.end()之前確保完成所有完成的任務,我能夠在Web應用程序中實現類似於此的任務,但在讓腳本返回之前,我沒有任何要調用的最終「事件」的等價物。

當前正在嘗試等待,直到callStack爲空爲止,請參閱以下我的(已損壞)函數。我剛剛發現這是一種無意義的方法,因爲在進入processObjWithRef中調用的任何異步函數之前,節點會等待processHub完成。

function processHub(hubFileContents){ 
    var callStack = []; 
    var myNewObj = {}; 
    processObjWithRef(samplePayload, myNewObj, callStack); 
    while(callStack.length>0){ 
     //do nothing 
    } 
    return 1 
} 

注:我已經嘗試了許多次以前實現這種行爲與像異步庫(見我在How can I make this call to request in nodejs synchronous?相關的問題),所以請大家建議基於「任何答案之前,回答和評論有考慮只是使用異步'。

+1

「我如何確保所有異步工作完成後才返回?」是一個毫無意義的問題 - 在所有異步任務完成之前,控制永遠不會返回到shell,所以在最後一個異步函數完成修復我的問題之前,請保留控制檯輸出。感謝所有提交答案。 – Trindaz 2012-03-30 03:48:51

回答

5

問題出在你設計的功能上。您想要從異​​步執行的任務列表中返回同步結果。

你應該用一個額外的參數來實現你的函數,這個參數將會是你要把結果放在這裏的回調函數(在這個例子中是1),以便一些消費者用它來做些事情。

此外,你需要在你的內部函數中有一個回調參數,否則你不會知道它何時結束。如果這最後一件事情是不可能的,那麼你應該做一些輪詢(可能使用setInterval)來測試callStack數組何時被填充。

請記住,在JavaScript中,你永遠不應該忙着等待。當它在單個進程上運行時,它將完全鎖定你的程序。

1

問題是node.js是單線程的,這意味着如果一個函數運行,其他運行(事件循環),直到該函數返回。所以你不能阻止一個函數在異步內容完成後返回。

例如,您可以設置一個計數器變量,用於統計啓動的異步任務,並使用異步代碼中的回調函數(在任務完成後調用該函數)減少該計數器。

5

在返回之前,您無法等待異步事件 - 這就是異步的定義!試圖強制Node進入這種編程風格只會讓你痛苦。一個天真的例子是定期檢查callstack是否爲空。

var callstack = [...]; 

function processHub(contents) { 
    doSomethingAsync(..., callstack); 
} 

// check every second to see if callstack is empty 
var interval = setInterval(function() { 
    if (callstack.length == 0) { 
    clearInterval(interval); 
    doSomething() 
    } 
}, 1000); 

相反,通常在Node中執行異步內容的方法是實現對函數的回調。

function processHub(hubFileContents, callback){ 
    var callStack = []; 
    var myNewObj = {}; 
    processObjWithRef(samplePayload, myNewObj, callStack, function() { 
    if (callStack.length == 0) { 
     callback(some_results); 
    } 
    }); 
} 

如果您確實想要退貨,請查看promises;他們保證立即發佈事件或在將來某個時候發佈事件,當他們解決時。

function processHub(hubFileContents){ 
    var callStack = []; 
    var myNewObj = {}; 
    var promise = new Promise(); 

    // assuming processObjWithRef takes a callback 
    processObjWithRef(samplePayload, myNewObj, callStack, function() { 
    if (callStack.length == 0) { 
     promise.resolve(some_results); 
    } 
    }); 

    return promise; 
} 

processHubPromise = processHub(...); 
processHubPromise.then(function(result) { 
    // do something with 'result' when complete 
}); 
0

你需要開始設計和思考異步,這可能需要一段時間才能習慣。這是一個簡單的例子,你可以在函數調用之後處理諸如「返回」之類的東西。

function doStuff(param, cb) { 
    //do something 
    var newData = param; 
    //"return" 
    cb(newData); 
} 

doStuff({some:data}, function(myNewData) { 
    //you're done with doStuff in here 
}); 

還有在NPM提供了很多在async庫有幫助的實用功能。

3

deasync是desinged完全解決您的問題。只是

require('deasync').loopWhile(function(){return callStack.length>0;}); 
1

的Node.js運行在單線程事件循環,並利用做各種事情,如I/O操作的異步調用替換

while(callStack.length>0){ 
    //do nothing 
} 

,如果你需要等待一些異步操作執行額外的代碼 之前完成的,你可以嘗試使用異步 -

Node.js Async Tutorial

相關問題