2012-03-30 8 views
9

Tôi có một ứng dụng nút là không một ứng dụng web - nó hoàn thành một loạt các tác vụ không đồng bộ trước khi trở về 1. Ngay trước khi trở về, kết quả của chương trình được in trên bảng điều khiển.Cách viết một hàm node.js chờ một sự kiện kích hoạt trước khi trở về?

Làm cách nào để đảm bảo tất cả công việc không đồng bộ được hoàn tất trước khi trở về? Tôi đã có thể đạt được một cái gì đó tương tự như thế này trong một ứng dụng web bằng cách đảm bảo tất cả các nhiệm vụ mà chúng tôi đã hoàn thành trước khi gọi res.end(), nhưng tôi không có bất kỳ tương đương nào cho 'sự kiện' cuối cùng để gọi trước khi cho phép tập lệnh trả về.

Xem bên dưới để biết chức năng (bị hỏng) của tôi hiện tại, cố gắng đợi cho đến khi callStack trống. Tôi vừa phát hiện ra rằng đây là một kiểu tiếp cận vô nghĩa bởi vì nút chờ processHub hoàn tất trước khi nhập bất kỳ hàm không đồng bộ nào được gọi trong processObjWithRef.

function processHub(hubFileContents){ 
    var callStack = []; 
    var myNewObj = {}; 
    processObjWithRef(samplePayload, myNewObj, callStack); 
    while(callStack.length>0){ 
     //do nothing 
    } 
    return 1 
} 

Lưu ý: Tôi đã thử nhiều lần trước đây để đạt được loại hành vi với các thư viện như async (xem câu hỏi có liên quan của tôi tại How can I make this call to request in nodejs synchronous?) vì vậy hãy lấy câu trả lời và ý kiến ​​đó vào tài khoản trước khi đưa ra bất kỳ câu trả lời dựa trên ' chỉ cần sử dụng asynch '.

+1

"Làm thế nào để đảm bảo tất cả các công việc không đồng bộ được hoàn thành trước khi trở về ? " Là một câu hỏi vô nghĩa - điều khiển không bao giờ được trả về shell cho đến khi tất cả các tác vụ không đồng bộ đã hoàn thành, vì vậy để lại đầu ra console cho đến sau khi hàm không đồng bộ cuối cùng đã hoàn thành cố định vấn đề của tôi. Cảm ơn tất cả vì đã gửi câu trả lời. – Trindaz

Trả lời

5

Sự cố xảy ra với thiết kế của hàm. Bạn muốn trả về một biểu mẫu kết quả đồng bộ một danh sách các tác vụ được thực hiện không đồng bộ.

Bạn nên triển khai hàm của mình với tham số bổ sung sẽ là gọi lại nơi bạn sẽ đặt kết quả (trong trường hợp này, 1) cho một số người tiêu dùng làm điều gì đó với nó.

Ngoài ra, bạn cần phải có tham số gọi lại trong hàm bên trong của mình, nếu không bạn sẽ không biết khi nào kết thúc. Nếu điều cuối cùng này là không thể, sau đó bạn nên làm một số loại bỏ phiếu (sử dụng setInterval có lẽ) để kiểm tra khi mảng callStack được điền.

Hãy nhớ rằng, trong Javascript bạn sẽ không bao giờ phải chờ đợi bận rộn. Điều đó sẽ khóa chương trình của bạn hoàn toàn khi nó chạy trên một tiến trình duy nhất.

1

Vấn đề là node.js là một luồng, có nghĩa là nếu một hàm chạy, không có gì khác chạy (vòng lặp sự kiện) cho đến khi hàm đó trả về. Vì vậy, bạn không thể chặn một chức năng để làm cho nó trở lại sau khi công cụ async được thực hiện. Bạn có thể, ví dụ, thiết lập một biến đếm đếm bắt đầu nhiệm vụ không đồng bộ và giảm truy cập bằng cách sử dụng một hàm gọi lại (được gọi sau khi tác vụ đã hoàn thành) từ mã async của bạn. Ví dụ:

5

Bạn không thể đợi sự kiện không đồng bộ trước khi trở về - đó là định nghĩa không đồng bộ! Cố gắng để buộc Node vào phong cách lập trình này sẽ chỉ khiến bạn đau đớn. Một ví dụ ngây thơ sẽ là kiểm tra định kỳ để xem liệu callstack có trống không.

var callstack = [...]; 

function processHub(contents) { 
    doSomethingAsync(..., callstack); 
} 

// check every second to see if callstack is empty 
var interval = setInterval(function() { 
    if (callstack.length == 0) { 
    clearInterval(interval); 
    doSomething() 
    } 
}, 1000); 

Thay vào đó, cách thông thường để thực hiện công cụ async trong Nút là thực hiện gọi lại cho hàm của bạn.

function processHub(hubFileContents, callback){ 
    var callStack = []; 
    var myNewObj = {}; 
    processObjWithRef(samplePayload, myNewObj, callStack, function() { 
    if (callStack.length == 0) { 
     callback(some_results); 
    } 
    }); 
} 

Nếu bạn thực sự muốn trả lại nội dung nào đó, hãy xem promises; chúng được đảm bảo phát ra một sự kiện ngay lập tức hoặc tại một số điểm trong tương lai khi chúng được giải quyết.

function processHub(hubFileContents){ 
    var callStack = []; 
    var myNewObj = {}; 
    var promise = new Promise(); 

    // assuming processObjWithRef takes a callback 
    processObjWithRef(samplePayload, myNewObj, callStack, function() { 
    if (callStack.length == 0) { 
     promise.resolve(some_results); 
    } 
    }); 

    return promise; 
} 

processHubPromise = processHub(...); 
processHubPromise.then(function(result) { 
    // do something with 'result' when complete 
}); 
0

Bạn sẽ cần bắt đầu thiết kế và suy nghĩ không đồng bộ, có thể mất một chút thời gian để làm quen trước. Đây là một ví dụ đơn giản về cách bạn sẽ giải quyết một cái gì đó như "trở về" sau một cuộc gọi chức năng.

function doStuff(param, cb) { 
    //do something 
    var newData = param; 
    //"return" 
    cb(newData); 
} 

doStuff({some:data}, function(myNewData) { 
    //you're done with doStuff in here 
}); 

Ngoài ra còn có rất nhiều chức năng tiện ích hữu ích trong thư viện async sẵn trên NPM.

3

deasync được giải quyết để giải quyết vấn đề của bạn chính xác. Chỉ cần thay thế

while(callStack.length>0){ 
    //do nothing 
} 

với

require('deasync').loopWhile(function(){return callStack.length>0;}); 
1

Node.js chạy trên Một vòng lặp sự kiện ren SINGLE và thúc đẩy các cuộc gọi không đồng bộ để làm những việc khác nhau, như/O hoạt động.

nếu bạn cần phải chờ đợi cho một số hoạt động không đồng bộ để kết thúc trước khi thực hiện thêm đang bạn có thể thử sử dụng Async -

Node.js Async Tutorial