2013-12-17 3 views
2

그래서 중첩 된 비동기 코드가 함께 작동하며 멋진 결과를 얻었을 때를 제외하고 모두 괜찮은 것처럼 보입니다. 일련의 블록의 마지막 기능은 foreach는이다 : 그 다음 async.parallel로 전환비동기를 올바르게 사용 (forEach와 함께)

순서대로 실행되지 않습니다 다음과 같은 덩어리를 추적 관리 : 나는하여이 코드를 테스트

async.forEach(array, function(elem, callback) { 
     async.parallel([ 
      function(callback) { 
       database-call-A(elem, unction(err, data) { 
        if(err){ 
         console.log("error on first parallel"); 
         callback({err: false}); // will break out 
        } else { 
         elem.c = data; 
         callback(); 
        } 
       }); 
      }, 
      function(callback) { 
       database-call-B(elem, function(err, data) { 
        if(err){ 
         console.log("error on first parallel"); 
         callback({err: false}); // will break out 
        } else { 
         elem.c = data; 
         callback(); 
        } 
       }); 
      } 
     ]); // end async.parallel 

     // if forEach needs a callback after every iteration (which I think it does?) 
     console.log("PRINTS N TIMES - ONCE FOR EVERY ITERATION"); 
     callback(); // both parallel functions have run, call back forEach 

}); // end forEach 

console.log("Donions - prints when finished"); 

사방에 인쇄 진술을 던지면서, "N 개의 시간 인쇄 ..."가 N 번 실행되었다는 것을 알아 차렸다. 그런 다음 "Donions .."를 얻었고 그런 다음 내 무언가를했다. 및 기타 물건(); 내 async.parallel에서 호출되기 시작했다.

async.parallel의 콜백을 기다리지 않고 forEach 반복을 수행하는 이유는 무엇입니까?

답변

3

처음에는 async.forEach이 없지만 async.each 기능이 있습니다. async.parallel 함수는 모든 작업을 simoultanely 실행 한 다음 콜백이 정의 된 경우 콜백을 실행합니다.

소스에서 함수는 async.parallel이 실행되는 즉시 실행되며 모든 함수가 반환 된 후에 실행되지 않습니다. documentation을 읽어 보시기 바랍니다. 모든 병렬 기능 후 callback 실행하려면

함수 배열 한 후, 두 번째 파라미터로서 async.parallel 함수 콜백 '콜백이 호출되어, 사용자는 forEach를 전달한다.' 또한 콜백을 databaseCallAdatabaseCallB에 모두 전달해야하므로 콜백이 끝나면 콜백을 호출하여 조기에 실행되지 않도록해야합니다.

async.each(array, function(elem, callback) { 
    async.parallel([ 
     function(cb) { 
      databaseCallA(cb); 
      // if you have called the cb here, the `async.parallel` function would "think" that the databaseCallA has finished, even though it may not have started yet. 
     }, 
     function(cb) { 
      databaseCallB(cb): 
     } 
    ], callback); 
}); 

당신은 콜백 인수를 승인하고 그들의 작업을 완료 한 후에는 콜백을 호출 할 수 있도록 데이터베이스 호출 기능을 수정해야합니다.

비동기 호출의 요점은 작업이 끝나기를 기다리는 동안 다른 작업에 대한 리소스를 확보하는 것입니다. 코드는 계속 실행되지만 콜백 또는 이벤트 기반 알림을 사용하여 다른 사용자에게 알립니다. 비동기 작업이 완료되었습니다.

편집

모든 병렬 통화를 마친 후 무언가를 실행하려면 :

async.each(array, function(elem, callback) { 
    async.parallel([ 
     function(cb) { 
      // I use the setTimeout function to intentionally 
      // delay the response 
      setTimeout(function() { 
       // the first cb parameter is error, the second is result 
       // in case there was no error 
       cb(undefined, 'a'); 
      }, 500); 
     }, 
     function(cb) { 
      setTimeout(function() { 
       cb(undefined, 'b'); 
      }, 300); 
     }, 
     function(cb) { 
      setTimeout(function() { 
       cb(undefined, 'c'); 
      }, 800); 
     } 
    ], function(err, results) { 
     // this will be executed only after all three cb's are executed. In 
     // this case, after about 800ms. The results variable will be an 
     // array containing the resuts passed to each cb. In this case it 
     // will be ['a', 'b', 'c']. 

     // you could call the main callback here 
     callback(); 
    }); 
}, function(err) { 
    // this callback will be executed either after everything was done, 
    // or if an error has occurred. 
    if (err) { 
     handleError(err); 
     return; 
    } 

    // this should be executed after all `each` and `parallel` calls 
    // have finished. In this case, it should also be after about 800ms 
    // from the start, since everything was executed in parallel 
    console.log('finished'); 

    // now you are sure everything was done, do something afterwards 
    after(); 
}); 

// this will be executed immediately so don't put anything here 
// that depends on the outcome of the async calls above 
console.log('test'); 
+0

네가 맞아! 나는 조금 더 단순화했다. 좀 더 많은 정보를 얻기 위해 업데이트를 확인했다. (내 db 호출은 돌아 왔을 때 우리가 앞면에 좋았 기 때문에 호출했다.) - 나는 확실히 forEach가 실제로 컴퓨터가 있지만 API에서 찾을 수없는 이유를 궁금해했습니다. 각 경우에 어떤 것이 있는지 보도록하겠습니다. – gadu

+0

정확히 무엇이 문제입니까? – jeremija

+0

정확히 내가 설명한, 내 병렬 전에 내 병렬 실행 코드가 있어요 - 내 콜백 코드 때문에 이미 그 콜백이 일어난 때문에 forEach 밖으로 반환하지 않습니다. – gadu

0

나는이 답변을 잘 모르겠지만, 비동기 문서에 따르면, 나는 이렇게 생각합니다 :

async.forEach(array, function(elem, callback) { 
    async.parallel([ 
     function(callback) { 
      database-call-A(); 
      callback(); 
     }, 
     function(callback) { 
      database-call-B(): 
      callback(); // callback for second parallel function 
     } 
    ], function(err,result) { 
     // this code is executed when paralles functions ends 
     console.log("PRINTS N TIMES - ONCE FOR EVERY ITERATION"); 
     callback(); 
    }); // end async.parallel 

}); // end forEach 

으로합니다.

+0

데이터베이스 호출은 비동기이며,이 경우 데이터베이스 호출이 실제로 작업을 수행하기 전에 콜백이 실행됩니다. – jeremija

관련 문제