2014-04-01 3 views
3

나는 forEach 루프를 NodeJS에 가지고 있으며 일련의 키를 반복한다. 그 값은 Redis에서 비동기 적으로 검색된다. 루프 및 검색이 완료되면 해당 데이터 세트를 응답으로 반환하려고합니다.루프 내부에서 비동기 함수 완료 후 함수를 호출하는 방법은 무엇입니까?

데이터 검색이 비동기식이기 때문에 현재 내 문제는 응답을 보낼 때 배열이 채워지지 않습니다.

ForEach 루프와 함께 약속이나 콜백을 사용하여 응답이 데이터와 함께 전송되도록하려면 어떻게해야합니까?

exports.awesomeThings = function(req, res) { 
    var things = []; 
    client.lrange("awesomeThings", 0, -1, function(err, awesomeThings) { 
     awesomeThings.forEach(function(awesomeThing) { 
      client.hgetall("awesomething:"+awesomeThing, function(err, thing) { 
       things.push(thing); 
      }) 
     }) 
     console.log(things); 
     return res.send(JSON.stringify(things)); 
    }) 
+0

이 문제에는 많은 품질 보증이 있습니다. 일부는이 페이지의 오른쪽에 나열되어 있습니다. –

+1

지금 당장 약속 라이브러리를 사용하는 것이 좋습니다. [소개가 있습니다] (http://margaine.com/bluebird/) –

+0

@dystroy 그 질문에 대한 유망한 답변을 추가하는 것을 고려해야합니다. 현재는 다소 추한 것입니다. 또한, 무언가 뭔가 비동기 세마포어. –

답변

10

여기서는 Bluebird promises을 사용합니다. 코드의 의도가 명확하고 중첩되지 않는 방법에 유의하십시오. 의 promisify hgetall 통화와 클라이언트하자,

첫째 -

이제
var client = Promise.promisifyAll(client); 

,의는 .map과의 약속과 코드, .then 대신 노드 콜백 및 집계를 쓸 수 있습니다. .then은 비동기 작업이 완료되었음을 알리는 신호입니다. .map은 배열을 가져와 hgetall 호출과 같이 모두 비동기 작업으로 매핑합니다.

Bluebird가 promisifed 메소드에 접미어 Async을 추가하는 방법에 유의하십시오.

exports.awesomeThings = function(req, res) { 
    // make initial request, map the array - each element to a result 
    return client.lrangeAsync("awesomeThings", 0, -1).map(function(awesomeThing) { 
     return client.hgetallAsync("awesomething:" + awesomeThing); 
    }).then(function(things){ // all results ready 
     console.log(things); // log them 
     res.send(JSON.stringify(things)); // send them 
     return things; // so you can use from outside 
    }); 
}; 
+0

감사합니다. 이것은 완벽합니다. 나는 약속이 이것을위한 길일 것이라는 것을 알았지 만 (이 질문을 게시 한 이래로) 내가 발견 한 많은 해결책은 매우 장황했다. – Anonymous

+2

기꺼이 도와 드리겠습니다. 약속은 정말 강력한 추상화이며 코드를 멋지게 단순화합니다. 그들은 또한 위의 코드 중 하나라도 오류가있는 경우 디버깅 기능을 내장하고 있습니다. Bluebird 약속을 알게됩니다. 그것들은 잘 묶여 있고 멋지게 구성되며 실제로 필요한 동시성 프리미티브를 포함합니다. 그것들은 EcmaScript 6의 JavaScript의 일부이기도합니다. 다음 표준인데,이 표준을 사용하는 코드는 미래의 호환성이 있다고 가정하는 것이 합리적입니다. –

1

lib가 필요하지 않습니다. 파이처럼 쉽고, 비동기 루프 일뿐입니다. 오류 처리가 생략되었습니다. 병렬 비동기 루프를 수행해야하는 경우 카운터를 사용하십시오.

exports.awesomeThings = function(req, res) { 
    client.lrange("awesomeThings", 0, -1, function(err, awesomeThings) { 
     var len = awesomeThings.length; 
     var things = []; 
     (function again (i){ 
      if (i === len){ 
       //End 
       res.send(JSON.stringify(things)); 
      }else{ 
       client.hgetall("awesomething:"+awesomeThings[i], function(err, thing) { 
        things.push(thing); 

        //Next item 
        again (i + 1); 
       }) 
      } 
     })(0); 
}); 
관련 문제