6

说我有两种方法:

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

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

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

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

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

4

5 回答 5

5

要扩展我的评论...

async是Node.js常用的异步流控库。

async.parallel()可能会为此做得很好:

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

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

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

async.parallel([A, B], C);
于 2013-08-08T01:26:39.433 回答
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()
>
于 2013-08-08T18:13:46.257 回答
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]--;
    }
}
于 2013-08-08T01:43:45.353 回答
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
})
于 2017-03-08T16:25:07.360 回答
0

我们可以为此目的ayncawait例如:

async function Foo(){
   // function logic
}

这个 Foo 功能为:

await Foo();
于 2017-11-12T11:22:38.740 回答