2013-08-02 47 views
32

Tôi đang cố gắng thực hiện nhiều truy vấn MongoDB trước khi tôi tạo mẫu Jade, nhưng tôi không thể tìm ra cách đợi cho đến khi tất cả Truy vấn Mongo hoàn tất trước khi hiển thị mẫu .Node.js - chờ cho nhiều cuộc gọi không đồng bộ

exports.init = function(req, res){ 


     var NYLakes = {}; 
     var NJLakes = {}; 
     var filterNY = {"State" : "NY"}; 
     db.collection('lakes').find(filterNY).toArray(function(err, result) { 
      if (err) throw err; 
      NYLakes = result; 
     }); 

     var filterNJ = {"State" : "NJ"}; 
     db.collection('lakes').find(filterNJ).toArray(function(err, result) { 
      if (err) throw err; 
      NJLakes = result; 
     }); 

     res.render('explore/index', 
      { 
       NYlakes: NYLakes, 
       NJlakes: NJLakes 
      } 
     ); 

    }; 

Trả lời

17

Giả sử bạn muốn chạy hai thao tác song song thay vì chờ kết thúc trước khi bắt đầu tiếp theo, bạn sẽ cần theo dõi số lượng thao tác đã hoàn thành trong mỗi lần gọi lại.

Trong Node.js javascript liệu, một trong những cách để làm điều này sẽ là:

exports.init = function(req, res){ 
    var NYLakes = null; 
    var NJLakes = null; 
    var filterNY = {"State" : "NY"}; 

    db.collection('lakes').find(filterNY).toArray(function(err, result) { 
     if (err) throw err; 
     NYLakes = result; 
     complete(); 
    }); 

    var filterNJ = {"State" : "NJ"}; 
    db.collection('lakes').find(filterNJ).toArray(function(err, result) { 
     if (err) throw err; 
     NJLakes = result; 
     complete(); 
    }); 

    function complete() { 
     if (NYLakes !== null && NJLakes !== null) { 
      res.render('explore/index', { 
       NYlakes: NYLakes, 
       NJlakes: NJLakes 
      }); 
     } 
    } 

}; 

Về cơ bản những gì đang xảy ra ở đây là bạn nên kiểm tra ở phần cuối của mỗi hoạt động nếu tất cả trong số họ đã hoàn tất, và tại điểm đó bạn kết thúc hoạt động.

Nếu bạn đang thực hiện rất nhiều việc này, hãy xem thư viện async làm ví dụ về công cụ giúp bạn quản lý loại điều này dễ dàng hơn.

+0

Rất sạch sẽ. Tốt đẹp. –

+0

Điều này sẽ có một điều kiện chủng tộc. Nếu cả hai hoạt động async thực thi cho đến khi chúng được gọi là complete(), thì cả hai có thể gọi nó với điều kiện cần thiết để thực hiện phần thân của câu lệnh if(). Không thể, nhưng có thể. –

+0

@ ghert85 Trong môi trường đa luồng bạn muốn, nhưng node.js là chuỗi đơn. Vì vậy, mã không thể bị gián đoạn cho đến khi nó trở về vòng lặp sự kiện và điều kiện chủng tộc này không thể xảy ra. –

5

Bạn có thể sử dụng mô-đun async:

var states = [{"State" : "NY"},{"State" : "NJ"}]; 

var findLakes = function(state,callback){ 
    db.collection('lakes').find(state).toArray(callback); 
} 

async.map(states, findLakes , function(err, results){ 
    // do something with array of results 
}); 
52

Tôi là một fan hâm mộ lớn của gạch/lodash, vì vậy tôi thường sử dụng _.after, mà tạo ra một chức năng mà chỉ có thực hiện sau khi được gọi là một số lần nhất định.

var finished = _.after(2, doRender); 

asyncMethod1(data, function(err){ 
    //... 
    finished(); 
}); 

asyncMethod2(data, function(err){ 
    //... 
    finished(); 
}) 

function doRender(){ 
    res.render(); // etc 
} 

Kể từ javascript Tời định nghĩa của chức năng định nghĩa với cú pháp function funcName(), mã của bạn đọc một cách tự nhiên: từ trên xuống dưới.

+0

Tuyệt vời, cảm ơn :) – iConnor

1

Wait.for https://github.com/luciotato/waitfor

sử dụng Wait.for:

exports.init = function(req, res){ 

    var NYLakes = {}; 
    var NJLakes = {}; 

    var coll = db.collection('lakes'); 

    var filterNY = {"State" : "NY"}; 
    var a = wait.forMethod(coll,'find',filterNY); 
    NYLakes = wait.forMethod(a,'toArray'); 

    var filterNJ = {"State" : "NJ"}; 
    var b = wait.forMethod(coll,'find',filterNJ); 
    NJLakes = wait.forMethod(b,'toArray'); 

    res.render('explore/index', 
     { 
      NYlakes: NYLakes, 
      NJlakes: NJLakes 
     } 
    ); 

}; 

Yêu cầu song song sử dụng wait.for song song bản đồ:

exports.init = function(req, res){ 

    var coll = db.collection('lakes'); 

    //execute in parallel, wait for results 
    var result = wait.parallel.map(
        [{coll:coll,filter:{"State" : "NY"}} 
        , {coll:coll,filter:{"State" : "NJ"}}] 
        , getData); 

    res.render('explore/index', 
     { 
      NYlakes: result[0], 
      NJlakes: result[1] 
     } 
    ); 

}; 

//map function 
function getData(item,callback){ 
try{ 
    var a = wait.forMethod(item.coll,'find',item.filter); 
    var b = wait.forMethod(a,'toArray'); 
    callback (null, b); 
} catch(err){ 
    callback(err); 
} 

Tôi không quen thuộc với mongo, vì vậy bạn có thể phải điều chỉnh các cuộc gọi.

Các vấn đề liên quan