admin管理员组

文章数量:1242849

say I have 2 methods:

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

I want to execute:
function C();
after both A and B are finished.
what we usually do is to put function C in the callback like:

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

now if both A and B takes a long time, I don't want B to execute after A has been finished. instead I want to start them at the same time to enhance performance.
what I'm thinking is to implement something like a semaphore (not really a semaphore of course), it fires an event after both A and B are finished. so that I can call C from within the event.

what I want to know is, is there any library implemented the above function already? I believe I'm not the first one who wants to do it.
any help is appreciated.

say I have 2 methods:

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

I want to execute:
function C();
after both A and B are finished.
what we usually do is to put function C in the callback like:

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

now if both A and B takes a long time, I don't want B to execute after A has been finished. instead I want to start them at the same time to enhance performance.
what I'm thinking is to implement something like a semaphore (not really a semaphore of course), it fires an event after both A and B are finished. so that I can call C from within the event.

what I want to know is, is there any library implemented the above function already? I believe I'm not the first one who wants to do it.
any help is appreciated.

Share Improve this question asked Aug 8, 2013 at 1:08 yaoxingyaoxing 4,2032 gold badges23 silver badges33 bronze badges 1
  • 1 async.parallel() – Jonathan Lonowski Commented Aug 8, 2013 at 1:18
Add a ment  | 

5 Answers 5

Reset to default 5

To expand on my ment...

async is a monly used asynchronous flow control library for Node.js.

Its async.parallel() would probably do well for this:

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

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

It's possible that this can be shortened, but it depends on how each function interact with callbacks and whether they follow the mon Node.js pattern of error-first callbacks:

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

For the sake of pleteness and as mentioned above, the same result can be achieved using an external object to hold pletion state where both A() and B() check to see if the other has pleted and if so, invokes C(). As in:

var results={};

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

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

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

The results object can be replaced by adding a 'isComplete' flag to both A() and B(), as in:

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

And modifying onComplete to check this new flag:

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

Or, the same using events:

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('plete','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('plete','B');
    },3000);
};

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

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

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

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

which, when run, will produce:

>node example.js
running A()
running B()
B() is plete
A() is plete
running C()
>
async.parallel([
    function(){ ... },
    function(){ ... }
], callback);

from: https://github./caolan/async

so in your case:

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

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

without modules i guess it would look something like this:

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

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

or like this:

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

If you're running on ES6, you can use Promise.all. Here is the example code rewritten:

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

we can aync and await for this purpose for example:

async function Foo(){
   // function logic
}

and this Foo function as:

await Foo();

本文标签: javascriptnodejs wait for other methods to finish before executingStack Overflow