一尘不染

仅在完成多个其他功能后如何执行Javascript功能?

node.js

我的具体问题是,我需要执行(可能)大量的Javascript函数来准备类似批处理文件的内容(每个函数调用都会向同一批处理文件中添加一些信息),然后在所有这些调用完成之后,执行发送批处理文件的最终功能(例如,将其作为HTML响应发送)。我正在为此寻找一种通用的Javascript编程模式。

概括问题:给定Javascript函数funcA(),funcB()和funcC(),我将找出排序执行的最佳方法,以便仅在执行funcA和funcB之后才执行funcC。我知道我可以使用这样的嵌套回调函数:

funcA = function() {
    //Does funcA stuff
    funcB();
}
funcB = function() {
    //Does funcB stuff
    funcC();
}

funcA();

通过传递回调参数,我什至可以使此模式更通用一些,但是,此解决方案变得非常冗长。

我还熟悉Javascript函数链,其中的解决方案如下所示:

myObj = {}
myObj.answer = ""
myObj.funcA = function() {
    //Do some work on this.answer
    return this;
}
myObj.funcB = function() {
    //Do some more work on this.answer
    return this;
}
myObj.funcC = function() {
    //Use the value of this.answer now that funcA and funcB have made their modifications
    return this;
}
myObj.funcA().funcB().funcC();

虽然此解决方案对我来说似乎更干净一些,但随着您在计算中添加更多步骤,函数执行链会越来越长。

对于我的特定问题,执行funcA,funcB等的顺序无关紧要。因此,在上述解决方案中,从技术上讲,我正在做比所需的更多的工作,因为我将所有功能都以串行顺序放置。对我而言,最重要的是funcC(用于发送结果或触发请求的某些函数)仅在funcA和funcB完成所有执行后才调用。理想情况下,funcC可以某种方式侦听所有中间函数调用以完成,然后将执行?我希望学习一种通用的Javascript模式来解决此类问题。

谢谢你的帮助。

另一个想法:也许将共享库传递给funcA和funcB,当它们完成执行时,将共享库标记为sharedThing.funcA =“
complete”或sharedThing.funcB =“
complete”,然后以某种方式?当共享库达到所有字段都标记为完成的状态时,执行funcC。我不确定您到底可以怎样使funcC等待。

编辑:我应该注意,我正在使用服务器端Javascript(Node.js),并且我想学习一种模式来解决该问题,只需使用普通的旧Javascript(不使用jQuery或其他库)即可。当然,这个问题很普遍,以至于有一个干净的纯Javascript解决方案?


阅读 252

收藏
2020-07-07

共1个答案

一尘不染

如果要保持简单,可以使用基于计数器的回调系统。这是允许when(A, B).then(C)语法的系统草案。(when/
then实际上只是糖,但整个系统还是有争议的。)

var when = function() {
  var args = arguments;  // the functions to execute first
  return {
    then: function(done) {
      var counter = 0;
      for(var i = 0; i < args.length; i++) {
        // call each function with a function to call on done
        args[i](function() {
          counter++;
          if(counter === args.length) {  // all functions have notified they're done
            done();
          }
        });
      }
    }
  };
};

用法:

when(
  function(done) {
    // do things
    done();
  },
  function(done) {
    // do things
    setTimeout(done, 1000);
  },
  ...
).then(function() {
  // all are done
});
2020-07-07