2016-08-01 3 views
0

코드에 연결된 모든 데이터베이스 querys 실행 한 후에 returnFile 함수를 실행하려면 찾고 있어요하지만 문제는 어떤 응답이 쿼리 내부에서 마지막 될 말할 수 없습니다. 응답, 그래서 내가 생각했던 루프를 분리하고 그냥 마지막 콜백을 returnFile 함수를 실행하지만 그것은 극적으로 일을 늦출 것입니다.비동기 루프의 끝을 결정

for (var i = 0, len = articleRevisionData.length; i < len; i++) { 
    tagNames=[] 
    console.log("step 1, "+articleRevisionData.length+" i:"+i); 
    if(articleRevisionData[i]["tags"]){ 
     for (var x = 0, len2 = articleRevisionData[i]["tags"].length; x < len2; x++) { 
      console.log("step 2, I: "+i+" x: "+x+articleRevisionData[i]["articleID"]) 
      tagData.find({"tagID":articleRevisionData[i]["tags"][x]}).toArray(function(iteration,len3,iterationA,error, resultC){ 
       console.log("step 3, I: "+i+" x: "+x+" iteration: "+iteration+" len3: "+len3) 
       if(resultC.length>0){ 
        tagNames.push(resultC[0]["tagName"]); 
       } 
        //console.log("iteration: "+iteration+" len: "+len3) 
       if(iteration+1==len3){ 
        console.log("step 4, iterationA: "+iterationA+" I: "+iteration) 
        articleRevisionData[iterationA]["tags"]=tagNames.join(","); 
       } 
      }.bind(tagData,x,len2,i)); 
     } 
    } 
    if(i==len-1){ 
     templateData={ 
      name:userData["firstName"]+" "+userData["lastName"], 
      articleData:articleData, 
      articleRevisionData:articleRevisionData 
     } 
     returnFile(res,"/usr/share/node/Admin/anonymousAttempt2/Admin/Articles/home.html",templateData); 
    } 
} 
+0

다른 사람들이 이미이 문제를 해결했습니다. 나는 Caolan의 AyncJS 라이브러리와 같은 것을 사용할 것을 제안 할 것이다. 특히, eachLimit : http://caolan.github.io/async/docs.html#.eachLimit – Brant

+1

사용 Promise의, 특히 Promise.all - 라이브러리가 필요 없음 –

+0

@JaromandaX 아이디어에 감사하지만 확실하지 않습니다. id가 루프의 끝에서 호출하는 것처럼 resolve 함수를 호출 할 수있을 때 모든 쿼리가 반환되지 않았을 수 있으며 쿼리 내부에서 호출하고 싶다면 그 것을 알 수있는 방법이 없습니다. 검색어가 마지막 것입니까? –

답변

0

거의 당신이 발견 한, 당신은 알 수 없다, 때문에 루프 내에서 비동기 함수를 호출하는 것은 좋은 생각입니다 완료되면 모든 통화 (비동기의 성격이다.)

예제에서 비동기 호출 중 이 동시에 실행되므로 사용자가 원하는 것보다 많은 시스템 리소스를 사용할 수 있습니다. 어떤 "콜백 지옥 부족,

const EventEmitter = require('events'); 

const emitter = new EventEmitter(); 

let iterations = articleRevisionData.length; 

// start up state 
emitter.on('start',() => { 
    // do setup here 
    emitter.emit('next_iteration'); 
}); 

// loop state 
emitter.on('next_iteration',() => { 
    if(iterations--) { 
    asyncFunc(args, (err,result) => { 
     if(err) { 
     emitter.emit('error', err); 
     return; 
     } 
     // do something with result 
     emitter.emit('next_iteration'); 
    }); 
    return; 
    } 
    // no more iterations 
    emitter.emit('complete'); 
}); 

// error state 
emitter.on('error', (e) => { 
    console.error(`processing failed on iteration ${iterations+1}: ${e.toString()}`); 
}); 

// processing complete state 
emitter.on('complete',() => { 
    // do something with all results 
    console.log('all iterations complete'); 
}); 

// start processing 
emitter.emit('start'); 

참고하는 방법을 간단하고이 코드는 청소 :

나는 이러한 종류의 문제에 대한 최적의 솔루션이 같이 실행 흐름을 관리하는 이벤트를 사용하는 것으로 나타났습니다 ", 그리고 프로그램 흐름을 시각화하는 것이 얼마나 쉬운지를 보여줍니다.

그것은 또한 당신을 당신이 (doWhile는, doUntil는,지도 축소/큐 노동자 등) 이 실행 제어의 모든 종류를 사용하여 이벤트를 표현할 수 및 이벤트 처리는 노드의 가장 핵심이기 때문에 것을 주목할 필요가있다 이런 식으로 그들을 사용하면 모든 해결책이 아니라는 사실을 알게 될 것입니다.

노드의 이벤트 처리에 대한 자세한 내용은 Node Events을 참조하십시오.

관련 문제