繁体   English   中英

如何在解决多个函数后运行函数?

[英]How to run a function only after multiple functions have been resolved?

我有几个功能,基本上准备我的应用程序。 一旦这些准备功能完成,我想运行我的应用程序的主循环。

因此,虽然准备功能彼此异步,但主循环仅在所有准备功能都已解决时运行。

function prep1(x) { do something };
function prep2(x) { do something };
function prep3(x) { do something };

function mainLoop(x) { only start this function when all 3 prep ones are resolved };

我基本上在nodejs中学习控制流。 我的问题是如何通过以下方式实现我的需求:

  1. 回调
  2. 事件
  3. promises(如果使用库,名称就足够了)

在Node.JS中有一些不同的控制流方式。 这种“传统”最直接的方式是使用回调 ,但这会导致我们称之为“回调地狱”或回旋镖效应。 您还可以使用promises库来处理回调地狱 在Node.JS中进行控制流(以及其他)的另一种方法是使用流。

请参阅下文,了解不同控制流程技术的示例。

使用回调的示例:

function prep1(x, cb) { do something; cb(); };
function prep2(x, cb) { do something; cb(); };
function prep3(x, cb) { do something; cb(); };

function mainLoop(x) { };

prep1(x, function () {
    prep2(y, function () {
        prep3(z, function () {
            mainLoop();
        });
    });
});

// could be shortened to
prep1(x, prep2(y, prep3(z, mainLoop)));

正如您所看到的,这可能导致一些非常丑陋的代码。 另请注意,此代码不是并行运行,而是串行运行。 如果要并行运行此操作,请参见下文,了解如何在每个准备函数中进行某种异步操作。

使用并行回调的示例:

// cb() is called inside some async operation
function prep1(x, cb) { do async; cb(y); };
function prep2(x, cb) { do async; cb(y); };
function prep3(x, cb) { do async; cb(y); };

function mainLoop(x) {
    // x is an array of values given by the callback in prep1-3
};

var numCalls = 0, result = [];
function maybeCallMainLoop(data) {
   if (++numCalls !== 3) {
       // Accumulate all responses given by  argument y from prep1-3
       result.push(data);
       return;
   }
   // run main loop when all functions are called
   mainLoop(result);
}

prep1(x, maybeCallMainLoop);
prep2(y, maybeCallMainLoop);
prep3(z, maybeCallMainLoop);

这并不是最干净,最健壮的方式。 想要下一个例子,一个更好的方法。


解决这个问题的一种更加清晰的方法是使用异步库 更具体地说是#parallel方法

使用异步库#parallel方法的示例

// Signature of the callback: callback(error, value)
function prep1(x, cb) { do something; cb(null, "value"); };
function prep2(x, cb) { do something; cb(null, "value"); };
function prep3(x, cb) { do something; cb(null, "value"); };

function mainLoop(error, x) { };

async.parallel([
    prep1,
    prep2,
    prep3
], mainLoop);

请参阅异步自述文件更多信息


如你所说,第三种方法是使用promises。 你会从每个准备函数返回一个promise,而不是等待mainLoop

您可以使用Q库 ,它是符合A *的承诺库。

使用带有Q库的 promises的示例

var Q = require('q');

// Signature of the callback: callback(error, value)
function prep1(x) { 
    // do something; 
    var deferred = Q.defer();
    deferred.resolve() // resolve promise
    return deferred.promise;
};
function prep2(x) { // same as prep1 };
function prep3(x) { // same as prep1 };

function mainLoop(result) { };

// Q.all returns a promise that is 
// resolved when all promises given are resolved
Q.all([
    prep1(x),
    prep2(y),
    prep3(z)
]).then(mainLoop);

请参阅Q.all的文档


这是解决问题的一些方法。 我并没有真正看到使用事件以一种漂亮的方式解决这个问题的方法 - 但它看起来很像并行回调的例子。 带有一个标志,指示完成的准备功能的数量。

您可以看到使用async或promises之类的东西很容易理解,也很容易理解。 如果您只想获得“瘦”(具有低圈复杂度的函数)的结果,我可能建议使用async 如果您的准备工作以不同方式使用某些复杂性和/或结果,那么承诺将是最好的方法。

关于溪流的小尾注

在Node.JS中,您还有一些称为流的东西。 以最基本的方式,流是具有背压(一种停止数据流的方式)功能的可管理事件发射器。 爸爸看一个简单的比喻,什么是流?

使用流,您可以拥有源并通过不同的转换流管道它,并使用某种接收器或端点结束流。 这是一个系列而不是并行,但你可以用流做更多的事情。 流与承诺有一些共性。

使用流的示例

function prep1(x) { return stream; };
function prep2(x) { return stream; };
function prep3(x) { return stream; };

function mainLoop(result) { };

// Some start. E.g fs.createReadStream("somefile")
someStartStream
   .pipe(prep1(x))
   .pipe(prep2(y))
   .pipe(prep3(z))
   .on('end', mainLoop);

同样,这是一个序列,而不是平行。 这只是为了表明在Node.JS的控制流中你也可以使用流。

祝你好运!

您还可以使用名为nimble的模块。

npm install nimble --save

然后按如下方式构造代码:

var flow = require('nimble');

flow.series([
     function (callback) {
          function prep1(x) { do something };
          callback();
     },
     function (callback) {
          function prep2(x) { do something };
          callback();
     },
     function(callback) {
          function prep3(x) { do something };
          callback();
     },
     function(callback) {
          function mainLoop(x) { };
          callback();
     }
]);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM