2013-08-02 15 views
32

Jade 템플릿을 렌더링하기 전에 여러 MongoDB 쿼리를 작성하려고하지만 템플리트를 렌더링하기 전에 모든 Mongo 쿼리가 완료 될 때까지 기다리는 방법을 알 수 없습니다 .Node.js - 여러 비동기 호출 대기

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

    }; 

답변

17

오히려 하나가 다음을 시작하기 전에, 각 콜백 완료 얼마나 많은 작업을 추적해야합니다 완료 될 때까지 기다리지 않고 병렬로 두 개의 작업을 실행하려는 가정. 원시 Node.js를의 자바 스크립트에서

,이 작업을 수행하는 하나 개의 방법이 될 것이다 :

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

}; 

기본적으로 여기에서 일어나고있는 것은 당신이 그들을 모두 완료 한 경우 각 작업의 끝에서 확인하고 있다는 것입니다 그 점에서 당신은 작업을 마쳤습니다.

이러한 작업을 많이 수행하는 경우 이러한 종류의 작업을보다 쉽게 ​​관리 할 수있는 도구의 예로, async 라이브러리를 살펴보십시오. 내가 밑줄/lodash의 큰 팬이에요

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 
}); 
+0

매우 깨끗합니다. 좋은. –

+0

이것은 경쟁 조건이 있습니다. 두 비동기 작업이 complete()를 호출하기 전에 바로 실행하면 complete()에서 if 문의 본문을 실행하는 데 필요한 조건으로 호출 할 수 있습니다. 있을 법하지는 않지만 가능합니다. –

+0

@ ghert85 다중 스레드 환경에서는 올바르게 작동하지만 node.js는 단일 스레드입니다. 따라서 이벤트 루프로 돌아가고이 경쟁 조건이 발생할 때까지 코드를 인터럽트 할 수 없습니다. –

5

당신은 async 모듈을 사용할 수 있습니다. function funcName() 구문 정의 함수의 정의를 호이스트 자바 스크립트 때문에

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

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

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

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

, 당신의 코드는 자연스럽게 읽 위에서 아래를. 뭘요를 사용

52

, 그래서 나는 보통 시간의 특정 번호 호출 후 실행하는 함수를 만듭니다 _.after을 사용

+0

우수, 감사합니다 :) – iConnor

1

뭘요 https://github.com/luciotato/waitfor

:

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

}; 

병렬지도 뭘요 사용하여 병렬로 요청 :

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

나는 익숙하지 않다 몽고와 함께, 그래서 당신은 전화를 조정할 수 있습니다.