Javascript 如何编写node.js函数,在';返回';?

Javascript 如何编写node.js函数,在';返回';?,javascript,node.js,asynchronous,synchronous,Javascript,Node.js,Asynchronous,Synchronous,我有一个不是web应用程序的节点应用程序,它在返回1之前完成了一系列异步任务。返回前,程序的结果立即打印到控制台 如何确保在返回之前完成所有异步工作?通过确保在调用res.end()之前完成了所有任务,我可以在web应用程序中实现类似的功能,但在让脚本返回之前,我没有任何等效的方法来调用最终的“事件” 请参阅下文,了解我的(已断开)函数当前正在尝试等待,直到callStack为空。我刚刚发现这是一种毫无意义的方法,因为node在进入processObjWithRef中调用的任何异步函数之前都会等

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


如何确保在返回之前完成所有异步工作?通过确保在调用res.end()之前完成了所有任务,我可以在web应用程序中实现类似的功能,但在让脚本返回之前,我没有任何等效的方法来调用最终的“事件”

请参阅下文,了解我的(已断开)函数当前正在尝试等待,直到callStack为空。我刚刚发现这是一种毫无意义的方法,因为node在进入processObjWithRef中调用的任何异步函数之前都会等待processHub完成

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

注意:我以前曾多次尝试使用async之类的库来实现这种行为(请参阅我的相关问题),因此,在根据“just use asynch”提出任何答案之前,请考虑其中的答案和注释。

问题在于函数的设计。您希望从异步执行的任务列表中返回同步结果

您应该使用一个额外的参数来实现您的函数,该参数将作为回调函数,您可以将结果(在本例中为1)放在该回调函数中,以便某些使用者使用它做一些事情

您还需要在内部函数中包含回调参数,否则您将不知道它何时结束。如果最后一件事不可能,那么您应该进行某种轮询(可能使用setInterval)来测试何时填充callStack数组


请记住,在Javascript中,永远不要进行繁忙的等待。这将完全锁定在单个进程上运行的程序。

问题在于node.js是单线程的,这意味着如果一个函数运行,那么在该函数返回之前,其他任何函数都不会运行(事件循环)。因此,您不能阻止一个函数,使其在异步操作完成后返回


例如,您可以设置一个计数器变量,对启动的异步任务进行计数,并使用回调函数(在任务完成后调用)从异步代码中递减计数器。

您不能等待异步事件返回,这就是异步的定义!试图强迫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);
相反,在节点中执行异步操作的通常方法是实现对函数的回调

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

您需要开始异步设计和思考,这可能需要一段时间来适应。这是一个简单的例子,说明了如何处理函数调用后“返回”之类的问题

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上的库中还有很多有用的实用函数。

旨在准确地解决您的问题。替换

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


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

如果在执行其他代码之前需要等待许多异步操作完成 您可以尝试使用异步-


“如何确保在返回之前完成所有异步工作?”是一个毫无意义的问题-在所有异步任务完成之前,控件永远不会返回到shell,因此将控制台输出保留到最后一个异步函数完成之后,可以修复我的问题。感谢大家提交答案。投票被否决,因为这没有回答问题。在某些情况下,您可能编写一个小的命令行程序或AWS Lambda,而不关心主线程是否被阻塞。
require('deasync').loopWhile(function(){return callStack.length>0;});