2013-08-08 9 views
5

sagen, ich habe zwei Methoden:NodeJS: Warten auf andere Methoden vor beenden Ausführung

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

ich ausführen wollen:
Funktion C();
nachdem beide A und B fertig sind.
was wir normalerweise tun ist Funktion C in der Callback setzen wie:

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

jetzt, wenn sowohl A als auch B eine lange Zeit in Anspruch nehmen, ich will nicht, B ausgeführt werden, nachdem A beendet ist. stattdessen möchte ich sie gleichzeitig starten, um die Leistung zu verbessern.
was ich denke ist, etwas wie ein Semaphor (nicht wirklich ein Semaphor natürlich) zu implementieren, es feuert ein Ereignis ab, nachdem sowohl A als auch B beendet sind. damit ich C innerhalb des Ereignisses anrufen kann.

was ich wissen möchte, ist, gibt es irgendeine Bibliothek implementiert die obige Funktion bereits? Ich glaube, ich bin nicht der erste, der das machen will.
jede Hilfe wird geschätzt.

+1

[ ' async.parallel() '] (https://github.com/caolan/async#parallel) –

Antwort

5

auf meinen Kommentar zu erweitern ...

async eine Steuer Bibliothek commonly used asynchronen Fluss ist für Node.js.

Sein async.parallel() wahrscheinlich gut tun würde dafür:

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

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

Es ist möglich, dass diese verkürzt werden können, aber es hängt davon ab, wie jede Funktion mit Rückrufen interagieren und ob sie folgen dem gemeinsame Node.js Muster von error -first Rückrufe:

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

Ich fand eine andere Bibliothek https://github.com/creationix/step, es scheint th Sie machen dasselbe. Wie auch immer, das löst meine Frage. Vielen Dank. – yaoxing

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

aus: https://github.com/caolan/async

so in Ihrem Fall:

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

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

ohne Module ich denke, es wie folgt aussehen würde:

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

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

oder so:

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

1. Handbuch ist zuverlässiger, weil, wenn "A" Callback D ruft, bevor das B hat sogar Zeit zu starten. Oder ich bin mir nicht sicher. –

2

Aus Gründen der Vollständigkeit und Wie oben erwähnt, kann das gleiche Ergebnis erreicht werden, indem ein externes Objekt verwendet wird, um den Abschlusszustand zu halten, wobei sowohl A() als auch B() prüfen, ob der andere abgeschlossen ist, und wenn ja, ruft C() auf.Wie 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(); 
} 

Die Ergebnisse Objekt kann Flagge durch Hinzufügen einer 'isComplete' ersetzt werden, um sowohl A() und B(), wie es in:

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

und Ändern onComplete diese neuen zu überprüfen Flagge:

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

Oder die Verwendung derselben Ereignisse:

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(); 

die, wenn sie ausgeführt werden, erzeugt:

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

Wenn Sie auf ES6 laufen lassen, Sie Promise.all verwenden können. Hier ist der Beispiel-Code neu geschrieben:

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

wir können aync und erwarten zu diesem Zweck zum Beispiel:

async function Foo(){ 
    // function logic 
} 

und diese Foo Funktion als:

await Foo(); 
Verwandte Themen