如何编写一个node.js函数等待事件在“返回”之前触发?

我有一个不是 Web应用程序的节点应用程序 – 它在返回1之前完成了一系列asynchronous任务。在返回之前,立即将程序结果打印到控制台。

在返回之前,如何确保所有asynchronous工作都已完成? 我可以通过在调用res.end()之前完成所有完成的任务来完成类似于Web应用程序的任务,但是在让脚本返回之前,我没有任何要调用的最终“事件”的等价物。

看到下面我的(破碎)函数,试图等到callStack为空。 我刚刚发现这是一种无意义的方法,因为在进入processObjWithRef中调用的任何asynchronous函数之前,节点会等待processHub完成。

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

注意:以前我已经尝试了很多次,用像async这样的库来实现这种行为(请参阅我的相关问题: 如何使这个调用请求在nodejs中同步? ),所以请在提出任何build议之前将其答案和注释考虑在内基于“只使用asynchronous”的答案。

问题在于你devise的function。 您希望从asynchronous执行的任务列表中返回同步结果。

你应该用一个额外的参数来实现你的函数,这个参数将是你要把结果放在哪里(在这种情况下是1),以便一些消费者用它来做些事情。

你也需要在你的内部函数中有一个callback参数,否则你不知道什么时候结束。 如果这最后一件事情是不可能的,那么你应该做一些轮询(可能使用setInterval)来testingcallStack数组何时被填充。

请记住,在Javascript中,你永远不应该忙于等待。 这将完全locking您的程序,因为它在单个进程上运行。

在返回之前,您无法等待asynchronous事件 – 这就是asynchronous的定义! 试图强制节点进入这种编程风格只会让你痛苦。 一个天真的例子将是定期检查,看看是否是空的。

 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中执行asynchronous工作的通常方法是实现对函数的callback。

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

如果你真的想要退货,请查看承诺 ; 他们保证立即发布事件,或者在将来某个时候解决事件。

 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 }); 

deasync是desinged完全解决您的问题。 只要更换

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

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

问题是,node.js是单线程的,这意味着如果一个函数运行,没有别的运行(事件循环),直到该函数返回。 所以你不能阻止一个函数,使asynchronous的东西完成后返回。

例如,您可以设置一个计数器variables来计算启动的asynchronous任务,并使用callback函数(在任务完成后调用)从asynchronous代码中减去该计数器的值。

Node.js在单线程事件循环上运行,并利用asynchronous调用来执行各种操作,如I / O操作。

如果您需要在执行其他代码之前等待大量asynchronous操作完成,则可以尝试使用Async –

Node.jsasynchronous教程

你需要开始devise和思考asynchronous,这可能需要一点时间才能习惯。 这是一个简单的例子,你将如何在函数调用后处理“返回”之类的东西。

 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上的asynchronous库中还有许多有用的实用function。