在迭代完成之前,回调会触发

时间:2016-09-21 03:04:16

标签: javascript node.js

我在这个项目中使用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? 
    }

2 个答案:

答案 0 :(得分:1)

一种方法是使用本机承诺并等待异步调用完成

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

    Promise.all(promises).then(function() {
        cb(null, timeTable);
    });
}

只需使整个功能更好

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) { ... })

答案 1 :(得分:1)

您似乎没有使用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);
});