2016-08-01 62 views
0

在附加的代碼中,我希望在所有數據庫查詢都運行後運行函數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庫。具體來說,每個限制: http://caolan.github.io/async/docs.html#eachLimit – Brant

+1

使用Promise和更具體Promise.all - 無需庫 –

+0

@JaromandaX感謝您的想法,但我不確定當id能夠調用解析函數,就好像我在循環結束時調用它所有的查詢可能還沒有返回,如果我想從查詢內部調用它,我無法知道這一點查詢是最後一個? –

回答

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中事件處理的更多信息,請參閱Node Events