2016-09-21 51 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) { ... })