2013-08-08 31 views
5

nói rằng tôi có 2 phương pháp:nodejs: chờ đợi cho các phương pháp khác để kết thúc trước khi thực hiện

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

Tôi muốn thực hiện:
chức năng C();
sau khi cả A và B kết thúc.
những gì chúng ta thường làm là đặt chức năng C trong callback như:

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

bây giờ nếu cả A và B phải mất một thời gian dài, tôi không muốn B để thực hiện sau khi A đã được hoàn tất. thay vào đó tôi muốn bắt đầu chúng cùng một lúc để nâng cao hiệu suất.
những gì tôi đang nghĩ là thực hiện một cái gì đó giống như một semaphore (không thực sự là một semaphore tất nhiên), nó cháy một sự kiện sau khi cả hai A và B được hoàn thành. để tôi có thể gọi C từ bên trong sự kiện.

điều tôi muốn biết là, có thư viện nào đã triển khai chức năng ở trên không? Tôi tin rằng tôi không phải là người đầu tiên muốn làm điều đó.
bất kỳ trợ giúp nào được đánh giá cao.

+1

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

Trả lời

5

Mở rộng trên nhận xét của tôi ...

async là một thư viện kiểm soát commonly used dòng chảy không đồng bộ cho Node.js.

async.parallel() có lẽ sẽ làm tốt cho việc này:

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

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

Có thể là điều này có thể được rút ngắn, nhưng nó phụ thuộc vào cách mỗi chức năng tương tác với callbacks và liệu họ có làm theo mô hình chung của Node.js error callbacks -đầu tiên:

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

Tôi tìm thấy một thư viện khác https://github.com/creationix/step, có vẻ như thứ ey đang làm điều tương tự. Dù sao, điều này giải quyết câu hỏi của tôi. Cảm ơn. – yaoxing

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

từ: https://github.com/caolan/async

.210

như vậy trong trường hợp của bạn:

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

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

mà không module tôi đoán nó sẽ giống như thế này:

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

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

hay như thế này:

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

Hướng dẫn sử dụng đầu tiên đáng tin cậy hơn vì nếu 'A' gọi lại gọi lại D trước khi B có thời gian để bắt đầu. Hay không, tôi không chắc chắn. –

2

Vì lợi ích của sự hoàn chỉnh và như đã đề cập ở trên, kết quả tương tự có thể đạt được bằng cách sử dụng một đối tượng bên ngoài để giữ trạng thái hoàn thành trong đó cả A() và B() kiểm tra xem liệu cái kia đã hoàn thành chưa và nếu có, gọi C().Như trong:

var results={}; 

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

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

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

Đối tượng kết quả có thể được thay thế bằng cách thêm một lá cờ 'isComplete' cho cả hai A() và B(), như trong:

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

Và sửa đổi onComplete để kiểm tra mới này cờ:

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

Hoặc, cùng sử dụng các sự kiện:

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

mà khi chạy, sẽ sản xuất:

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

Nếu bạn đang chạy trên ES6, bạn có thể sử dụng Promise.all. Dưới đây là ví dụ mã viết lại:

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

chúng ta có thể ayncchờ cho mục đích này ví dụ:

async function Foo(){ 
    // function logic 
} 

và chức năng Foo này như:

await Foo(); 
Các vấn đề liên quan