nodejs:在执行之前等待其他方法完成

时间:2013-08-08 01:08:19

标签: javascript node.js

说我有两种方法:

function A(callback) { ... }
function B(callback) { ... }

我想执行:
    功能C();
A和B完成后。
我们通常做的是将函数C放在回调中,如:

A(function() {
  B(function() {
    C();
  });
});

现在如果A和B都需要很长时间,我不希望B在A完成后执行。相反,我想同时启动它们以提高性能 我在想的是实现类似信号量的东西(当然不是真正的信号量),它会在A和B都完成后触发事件。这样我就可以在活动中打电话给C.

我想知道的是,是否有任何库已实现上述功能?我相信我不是第一个想要这样做的人 任何帮助表示赞赏。

5 个答案:

答案 0 :(得分:5)

扩展我的评论......

async是Node.js的commonly used异步流控制库。

它的async.parallel()可能会做得很好:

async.parallel([
    function(done) {
        A(function () {
            done(null);
        });
    },

    function(done) {
        B(function () {
            done(null);
        });
    }
], function (err) {
    C();
});

这可能会缩短,但这取决于每个函数如何与回调交互,以及它们是否遵循error的常见Node.js模式 - 第一次回调:

async.parallel([A, B], C);

答案 1 :(得分:2)

为了完整性并且如上所述,使用外部对象保持完成状态可以实现相同的结果,其中A()和B()检查另一个是否已完成,如果是,则调用C ()。如:

var results={};

function onComplete(){
    if(results['A'] && results['B'] && !results['C']) {
        C();
    }
}

function A(){
    // ... 
    results['A']=true;
    onComplete();
}

function B(){
    // ... 
    results['B']=true;
    onComplete();
}

可以通过向A()和B()添加'isComplete'标志来替换结果对象,如:

function A(){
    // ...
    A.isComplete=true;
    onComplete();
}

修改onComplete以检查这个新标志:

function onComplete(){
    if(A.isComplete && ...
}

或者,使用相同的事件:

var util=require('util'),
    events=require('events'),
    EventEmitter=events.EventEmitter;

function F(){
    EventEmitter.call(this); // init ancestor
}

util.inherits(F,EventEmitter); // assign ancestor

F.prototype.A=function(){
    var self=this;
    console.log('running A()');
    setTimeout(function(){ // simulate long running code - 5 seconds
        F.prototype.A.isComplete=true;
        self.emit('complete','A');
    },5000);
};

F.prototype.B=function(){
    var self=this;
    console.log('running B()');
    setTimeout(function(){ // simulate long running code - 3 seconds
        F.prototype.B.isComplete=true;
        self.emit('complete','B');
    },3000);
};

F.prototype.C=function(){
    console.log('running C()');
};

var f=new F;
f.on('complete',function(which){ // onComplete handler
    console.log(which+'() is complete');

    if(F.prototype.A.isComplete && F.prototype.B.isComplete){
        f.C();
    }
});

// start it up
f.A();
f.B();

,在运行时,将产生:

>node example.js
running A()
running B()
B() is complete
A() is complete
running C()
>

答案 2 :(得分:1)

async.parallel([
    function(){ ... },
    function(){ ... }
], callback);

来自:https://github.com/caolan/async

所以在你的情况下:

async.parallel([funcA,funcB],funcC);

//function definitions
function funcA() {...}
function funcB() {...}
function funcC() {...}

没有模块我想它看起来像这样:

var numFuncs = 2;
A(D);
B(D);

and then 
function D() {
if(numFuncs==0){ C(); } else {
numFuncs--; 
}}

或者像这样:

A(D(C));
B(D(C));


function D() {
    var x = process.funcsToCall= process.funcsToCall || {};
    var f=arguments[0];
    (!x.hasOwnProperty(f.name))?x[f.name]=0:x[f.name]++;
    return function(){
       (x[f.name]==0)?f():x[f.name]--;
    }
}

答案 3 :(得分:0)

如果您在ES6上运行,则可以使用Promise.all。以下是重写的示例代码:

Promise.all([
  new Promise((resolve) => A(() => resolve())),
  new Promise((resolve) => B(() => resolve())),
]).then(() => {
  C()
}).catch(err => {
  // handle errors from function A, B and C
})

答案 4 :(得分:0)

我们可以 aync 等待用于此目的,例如:

async function Foo(){
   // function logic
}

并且这个Foo函数为:

await Foo();