2013-10-30 3 views
1

비동기 모듈을 사용하여 Node.js에 대한 '콜백 지옥'을 줄이려고합니다. 기본적으로 데이터베이스에서 일부 정보를 검색하고 내보기에 표시하려면 async.series을 사용하려고합니다. 그래도 내 생각에는 결과가 없습니다.Node.js 비동기 모듈 문제

// Search 
exports.search = function(req, res) { 

    var x = []; 



     async.series([ 
      function(cb) { 
       Lang.find({ lang: req.query.keyword }).sort({ verbal: -1 }).exec(function(err, langs) {    

        cb(null, langs); 

       }); 
      }, 

      function(cb) { 
       Human.find({}, function(err, humans) {    

        cb(null, humans); 
       }); 
      }], 

      function(err, results) { 
       if (err) { 
        res.send(500); 
       } 

       for(var i = 0; i < results[0].length; i++) { 
        for(var j = 0; j < results[1].length; j++) { 
         if(results[1][j]._id == results[0][i].human) { 
          x.push(results[1][j]); 
         } 
        } 
       } 

       res.render('myView', { title: 'Search Results', humans: x }); 
      } 
     ); 
    } 

내가 처음 랭 모델 (MongoDB를)를 쿼리하고 req.query.keyword 일치하는 레코드를 찾으려면 :

내가 지금까지 가지고있는 코드입니다. 그 후, 필자는 인간 모델을 쿼리하여 해당 언어 기술이있는 모든 인간을 찾고자합니다. 또한 FOR 루프는 Human이 여러 언어를 가질 수 있으므로 내 배열에서 중복을 제거하기위한 것입니다.

답변

0

코드를 올바르게 이해하면 async.waterfall을 대신 사용하는 것이 좋습니다. 한 함수의 결과를 인수로 전달합니다. 할 수있는 몇 가지 다른 최적화도 있습니다 :

async.waterfall([ 
    function(done) { 
    Lang 
     .find({ lang: req.query.keyword }) 
     .sort({ verbal: -1 }) // (not really useful) 
     .select('human')  // not strictly necessary, but saves a bit of space 
     .exec(done);   // short for : 
          // .exec(function(err, results) { 
          //  done(err, results); 
          // }); 
    }, 
    function(langs, done) { 
    // extract the 'human' property from each result 
    var _ids = langs.map(function(lang) { 
     return lang.human; 
    }); 

    // perform a query finding all humans in the list of ids 
    Human 
     .find({ _id : { $in : _ids } }) 
     .exec(done); 
    } 
], function(err, humans) { 
    if (err) 
    return res.send(500); 
    res.render('myView', { 
    title : 'Search Results', 
    humans: humans 
    }); 
}); 

편집 : 순서를 유지하고 this answer$or를 사용하여, 두 번째 쿼리에 대한 대안으로 이것을 시도 할 것을 제안하지 않습니다$in 때문에 :

... 
    function(langs, done) { 
    var query = langs.map(function(lang) { 
     return { _id : lang.human }; 
    }); 

    Human 
     .find({ $or : query }) 
     .exec(done); 
    } 
    ... 
+0

코드를 시험해 보았는데 완벽하게 작동합니다! 그래도 주문 내림차순 기능은 언어 스킬을 기준으로 결과가 내림차순으로 반환되기를 원하기 때문입니다. 예를 들어, 영어 실력이 5와 10 인 사람이 2 명인 경우 10 명이있는 사람을 검색 결과 목록의 첫 번째 사람으로 지정해야합니다. 이 스 니펫은 발견 한 순서대로 인간 목록을 반환합니다. –

+0

@shinpou 주문을 가져 오는 경우'$ in '을 사용하면 주문이 계속 유지 될지 확실하지 않습니다. 그래서 시험해주세요 :) – robertklep

+0

나는 그것을 시험해 보았습니다. 내가 찾고있는 것이 아닙니다. (그러나 여전히! 올바른 결과를 얻고 있습니다!) 고맙습니다! 아직도 어떤 방향으로 나를 가르쳐 주 시겠어요 (문서) 또는 done 콜백 함수에 대해 설명하십시오. 단순히 waterfall 함수에 통합되어 다음 함수에 매개 변수를 전달하는 데 사용됩니까? –