2012-04-24 35 views
14

Cách tốt nhất/thư viện để xử lý nhiều cuộc gọi lại không đồng bộ là gì? Ngay bây giờ, tôi có một cái gì đó như thế này:Javascript - đang đợi một số cuộc gọi lại không đồng bộ trở lại?

_.each(stuff, function(thing){ 
    async(thing, callback); 
}); 

tôi cần phải thực hiện một số mã sau khi gọi lại đã bị sa thải cho mỗi phần tử trong stuff.

Cách sạch nhất để thực hiện việc này là gì? Tôi đang mở để sử dụng thư viện.

+0

thể trùng lặp của [chờ trên nhiều không đồng bộ gọi để hoàn thành trước khi tiếp tục] (http://stackoverflow.com/questions/2768293/waiting-on-multiple-asynchronous-calls-to-complete-before-continuing) – RMalke

Trả lời

12

Có một thư viện tuyệt vời được gọi là Async.js giúp giải quyết các vấn đề như thế này với nhiều người trợ giúp điều khiển luồng không đồng bộ &. Nó cung cấp một số hàm forEach có thể giúp bạn chạy callbacks cho mọi mục trong một mảng/đối tượng.

Check-out: https://github.com/caolan/async#forEach

// will print 1,2,3,4,5,6,7,all done 

var arr = [1,2,3,4,5,6,7]; 

function doSomething(item, done) { 
    setTimeout(function() { 
    console.log(item); 
    done(); // call this when you're done with whatever you're doing 
    }, 50); 
} 

async.forEach(arr, doSomething, function(err) { 
    console.log("all done"); 
}); 
+0

Điều này là tốt, và nếu điều này có thể xử lý chuỗi cho tôi, tôi có thể thực hiện chuyển đổi này sau. Điều này có làm điều gì đó thông minh hơn đơn giản bằng cách sử dụng bộ đếm như _.after không? –

+0

Điều thú vị là bạn có thể làm 'async.forEachSerial' nếu bạn muốn chúng chạy cái khác. Nó mang lại cho bạn sự linh hoạt.Đối với một trường hợp sử dụng đơn giản, vâng điều đếm hoạt động tốt và được xây dựng thành gạch dưới. Làm đi! –

+0

Tôi bị thương cần sử dụng 'series' khá nhiều, và chuyển sang async đã dọn sạch mọi thứ * khá * một chút. Tôi cũng khá chắc chắn tôi phát hiện ra một vấn đề thời gian gọi lại trong quá trình này. –

0

Có bộ đếm, nói async_count. Tăng nó mỗi lần bạn bắt đầu một yêu cầu (bên trong vòng lặp của bạn) và có callback giảm nó bằng một và kiểm tra nếu không đạt được - nếu như vậy, tất cả các callbacks đã trở lại. EDIT: Mặc dù, nếu tôi là người viết bài này, tôi sẽ xâu chuỗi các yêu cầu thay vì chạy chúng song song - nói cách khác, tôi có một hàng đợi các yêu cầu và có cuộc gọi lại kiểm tra hàng đợi cho yêu cầu tiếp theo chế tạo.

28

Kể từ khi bạn đã sử dụng gạch dưới bạn có thể nhìn vào _.after. Nó thực hiện chính xác những gì bạn đang yêu cầu. Từ các tài liệu:

sau       _.after(count, function)

Tạo một phiên bản của các chức năng đó sẽ chỉ được chạy sau khi lần đầu tiên được gọi lần đếm. Hữu ích cho việc nhóm các câu trả lời không đồng bộ, nơi bạn muốn chắc chắn rằng tất cả các cuộc gọi không đồng bộ đã kết thúc, trước khi tiếp tục.

+1

Công trình này tuyệt vời. –

2

Tôi khuyên bạn nên https://github.com/caolan/async cho việc này. Bạn có thể sử dụng async.parallel để thực hiện việc này.

function stuffDoer(thing) { 
    return function (callback) { 
     //Do stuff here with thing 
     callback(null, thing); 
    } 
} 

var work = _.map(stuff, stuffDoer) 
async.parallel(work, function (error, results) { 
    //error will be defined if anything passed an error to the callback 
    //results will be an unordered array of whatever return value if any 
    //the worker functions passed to the callback 
} 
+0

Tại sao không phải là 'async.forEach'? –

+0

Tôi nghĩ rằng trong trường hợp này async.forEach và async.parallel về cơ bản giống hệt nhau. Các tài liệu trên forEach thậm chí còn nói "nó thực hiện chúng song song". Tên "song song" làm cho điều này rõ ràng hơn mặc dù. –

+0

Hmm, vâng có vẻ như forEach là phù hợp hơn trong trường hợp này vì nó sẽ xử lý các đóng cửa cho bạn và bạn chỉ có thể cung cấp cho nó một chức năng thường xuyên và danh sách dữ liệu. –

1

async.parallel()/async.series phải phù hợp với yêu cầu của bạn. Bạn có thể cung cấp với một cuộc gọi lại cuối cùng được thực thi khi tất cả các cuộc gọi REST thành công.

async.parallel([ 
    function(){ ... }, 
    function(){ ... } 
], callback); 
async.series([ 
    function(){ ... }, 
    function(){ ... } 
], callback); 
Các vấn đề liên quan