2016-09-21 4 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

Вы надеваете» t, похоже, использует любую функцию из библиотеки 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

Одним из способов было бы просто использовать собственные обещания и ждать асинхронной звонки закончить

Только что делает всю функцию thenable бы лучше

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) { ... }) 
Смежные вопросы