2016-09-21 53 views
2

我在此項目中使用async庫。一個函數(下面複製)包含一個嵌套循環來構建一個2D數組。在數組完全構建之前調用回調函數。我真的很想了解爲什麼會發生這種情況並瞭解更多最佳實踐。解決這個問題的最好方法是什麼?迭代完成前發生回調觸發

function getStopTimesForTrips(cb) { 
     timeTable.listOfTripIds.forEach(function(id){ 
      retrieveTimesByTrip(id, function(err, st){ 
       var tempArray = []; 
       st.forEach(function(st){ 
        tempArray.push(st.arrival_time); 
       }); 
       timeTable.stopTimes.push(tempArray); 
      }); 
     }); 
     // cb(null, timeTable); <- This line fires the callback before we finish building the array. 
     setTimeout(function(){cb(null, timeTable);},2500); // This effective solution is poor form. What's the correct way to solve this issue? 
    } 
+0

你甚至沒有使用庫提供的'async'方法。 – choz

+0

看起來像一個異步函數循環,但是你可以稱之爲回調而不用等待它們全部被調用。 –

回答

1

你不thenable會更好」似乎在使用來自async庫的任何功能。正確的解決方案是使用async

async.each(timeTable.listOfTripIds,function(id,cb2){ 
    retrieveTimesByTrip(id, function(err, st){ 
     var tempArray = []; 
     st.forEach(function(st){ 
      tempArray.push(st.arrival_time); 
     }); 
     timeTable.stopTimes.push(tempArray); 
     cb2(err); // Need to call this to tell async this iteration 
        // is done. Think of it as an async "return". 
    }); 
},function(err){ 
    // if we're here it means the `async.each` is done: 
    cb(null, timeTable); 
}); 
+0

謝謝!這正是我所期待的。 – StephenStephen

1

一種方法是隻使用原生的承諾,並等待異步調用完成

就使得整個功能

function getStopTimesForTrips() { 
    return Promise.all(
     timeTable.listOfTripIds.map(function(id) { 
      return new Promise(function(resolve, reject) { 
       retrieveTimesByTrip(id, function(err, st) { 
        if (err) return reject(); 
        resolve(
         st.map(function(item) { 
          return item.arrival_time; 
         }) 
        ); 
       }); 
      }); 
     }) 
    ); 
} 

getStopTimesForTrips().then(function(arrival_times) { ... }) 
相關問題