2013-08-08 11 views
5

powiedzieć Mam 2 metody:nodejs: Poczekaj na inne sposoby, aby zakończyć przed wykonaniem

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

Chcę wykonać:
funkcji C();
po zakończeniu A i B.
co zwykle robimy jest umieszczenie funkcji C w zwrotnego jak:

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

teraz, gdy oba A i B trwa długo, nie chcę B wykonać po zostało zakończone. zamiast tego chcę je uruchomić w tym samym czasie, aby zwiększyć wydajność.
to, co myślę, to zaimplementować coś w rodzaju semafora (oczywiście nie semafora), uruchamia zdarzenie po zakończeniu A i B. aby móc zadzwonić do C z wydarzenia.

co chcę wiedzieć, czy jest jakaś biblioteka zaimplementowana wyżej funkcja już? Wierzę, że nie jestem pierwszym, który chce to zrobić.
każda pomoc jest doceniana.

+1

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

Odpowiedz

5

Aby rozwinąć na mój komentarz ...

async jest biblioteką kontrola commonly used przepływu asynchroniczny dla Node.js.

Jego async.parallel() prawdopodobnie zrobić to dobrze:

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

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

Jest możliwe, że ten można skrócić, ale to zależy od tego, jak każda funkcja interakcji z wywołania zwrotne i czy odpowiadają one wspólną node.js wzór error -pierwsze callbacks:

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

Znalazłem inną bibliotekę https://github.com/creationix/step, wydaje się, że Oni robią to samo. W każdym razie to rozwiązuje moje pytanie. Dzięki. – yaoxing

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

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

więc w Twoim przypadku:

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

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

bez modułów Chyba to będzie wyglądać mniej więcej tak:

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

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

lub tak:

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

Pierwsza instrukcja jest bardziej niezawodna, ponieważ jeśli 'A' wywołuje jej wywołanie zwrotne D, zanim B ma czas na rozpoczęcie. Czy nie jestem pewien. –

2

Dla kompletności i jak wspomniano powyżej, ten sam wynik można osiągnąć przy użyciu zewnętrznego obiektu do utrzymywania stanu zakończenia, w którym zarówno A() i B() sprawdzają, czy drugi zakończył, a jeśli tak, wywołuje C().Jak w:

var results={}; 

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

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

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

Przedmiotem wyniki mogą być zastąpione przez dodanie flagi 'IsComplete' zarówno A() i B(), na przykład:

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

i modyfikowanie onComplete sprawdzić ten nowy Flaga:

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

Albo wykorzystujące te same wydarzenia:

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

, który po uruchomieniu będzie produkować:

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

Jeśli używasz na ES6, można użyć Promise.all. Oto przepisany przykład kodu:

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

możemy aync i czekają do tego celu na przykład:

async function Foo(){ 
    // function logic 
} 

i tej funkcji Foo jak:

await Foo(); 
Powiązane problemy