如何等待async.forEachOf完成,然后将结果发送到客户端?

时间:2019-06-06 14:16:10

标签: javascript node.js

我有一个/ get路由,该路由从数据库中获取一些数据并将其发送给用户。 问题是我在两个函数中使用了async.forEachOf语句。我不知道如何等到第二个async.forEachof完成后再将整个结果发送回用户。

我认为我需要使用Promise或类似的东西,但是我无法管理在函数中如何使用它。有人可以帮我这困扰我两天了。谢谢,祝你有美好的一天。

这些是功能:

function getSetsFromWorkout(workouts) {
const selectSetsQuery = "SELECT id, set_number, workoutFKEY FROM sets WHERE workoutFKEY = ?"

async.forEachOf(workouts, function (workout, key, callback) {
    const workoutId       = workout.id
    getConnection().query(selectSetsQuery, [workoutId], (err, setsRows, result) => {
        if (err) {
            console.log("Failed to query for users: "+ err)
            res.sendStatus(500)
            res.end()
        } else { 
            workout["sets"] = setsRows  
            getExercisesFromSets(workout)
        }
        callback()
    });
}, function (err) {
    if (err) console.log(err.message);
});
};

function getExercisesFromSets(sets) {
const selectExercisesQuery = "SELECT id, ex_time, type, ex_id FROM user_exercises WHERE setsFKEY = ?"

const allSets = sets["sets"]

async.forEachOf(allSets, function (set, key, callback) {
    const setId = set.id
    getConnection().query(selectExercisesQuery,[setId], (err, exercisesRows, result)=> {
        if (err) {
            console.log("Failed to query for users: "+ err)
            res.sendStatus(500)
            res.end()
        } else {
            console.log("add exercise")
            set["exercises"] = exercisesRows
            callback()
        }
    });

}, function(err) {
    if (err) console.log(err.message)
     console.log("ENDED")
     console.log(sets)
}); 
};

这是基于console.log()语句的输出。结果就是我需要的,但是我只在forEachOf循环完成后才知道如何发送它。

如果我将res.json(sets)放在这里,它将仅将forEachOf的第一个迭代发送回客户端,然后它将停止。

function(err) {
    if (err) console.log(err.message)
     console.log("ENDED")
     console.log(sets)
     **res.json(sets)**
}); 
 };

我需要等待所有迭代完成,然后将数据发送到sclient。

add exercise
add exercise
add exercise
ENDED

//MY data from db

add exercise
ENDED
// My other set of data from db

3 个答案:

答案 0 :(得分:1)

我认为您可以创建一个将由async.forEach回调函数调用的函数,以及一个用于检查两个进程是否都已结束的变量(例如,获得相同结果的某些不同方法)。像这样:

var ended = { array1: false, array2: false };
const dataToReturn = {};

const array1 = [];
async.forEachOf(array1, function (item, key, callback) {
    // do stuff
    dataToReturn.array1 = "first data";
    callback();
}, function (err) {
    if (err) console.log(err.message);
    else {
      ended.array1 = true;
      endProcess();
    }
});

const array2 = [];
async.forEachOf(array2, function (item, key, callback) {
    // do stuff
    dataToReturn.array2 = "first data";
    callback();
}, function (err) {
    if (err) console.log(err.message);
    else {
      ended.array2 = true;
      endProcess();
    }
});

function endProcess() {
    if (!ended.array1 || !ended.array2) return;
    res.json(dataToReturn);
}

答案 1 :(得分:0)

如果我理解正确,则需要发送所有锻炼集从selectExercisesQuery返回的锻炼集。下列带有注释突出显示的更改应该起作用:

function getSetsFromWorkout(workouts) {
const selectSetsQuery = "SELECT id, set_number, workoutFKEY FROM sets WHERE workoutFKEY = ?"

async.forEachOf(workouts, function (workout, key, callback) {
    const workoutId       = workout.id
    getConnection().query(selectSetsQuery, [workoutId], (err, setsRows, result) => {
        if (err) {
            console.log("Failed to query for users: "+ err)
            res.sendStatus(500)
            res.end()
        } else { 
            workout["sets"] = setsRows  
            getExercisesFromSets(workout)
        }
        callback()
    });
}, function (err) {
    if (err) console.log(err.message);
   res.send(workouts); // -------------------Workout object has all the info you need as it is being passed and updated by reference.
});
};

function getExercisesFromSets(sets) {
const selectExercisesQuery = "SELECT id, ex_time, type, ex_id FROM user_exercises WHERE setsFKEY = ?"

const allSets = sets["sets"]

async.forEachOf(allSets, function (set, key, callback) {
    const setId = set.id
    getConnection().query(selectExercisesQuery,[setId], (err, exercisesRows, result)=> {
        if (err) {
            console.log("Failed to query for users: "+ err)
            res.sendStatus(500)
            res.end()
        } else {
            console.log("add exercise")
            set["exercises"] = exercisesRows
            callback()
        }
    });

}, function(err) {
    if (err) console.log(err.message)
     console.log("ENDED")
     sets["sets"] = allSets //--------------assign the updated allSets array back to referenced sets.
     console.log(sets)
}); 
};

答案 2 :(得分:0)

您始终可以通过将第二个异步代码包装在返回的承诺中来为内部 async.forEachOfgetExercisesFromSets() 中的那个)使用承诺。并且只有在异步完成后,即在错误检查之后,承诺才会得到履行。然后只有在第二个函数被调用并且它完成了承诺(即在 promise.then() 中)之后才调用第一个函数的回调。这将确保仅在计算完一组练习中的所有练习后才计算该组。像这样:

function getSetsFromWorkout(workouts) {
    const selectSetsQuery = "SELECT id, set_number, workoutFKEY FROM sets WHERE workoutFKEY = ?"
    async.forEachOf(workouts, function (workout, key, callback) {
        const workoutId = workout.id
        getConnection().query(selectSetsQuery, [workoutId], (err, setsRows, result) => {
            if (err) {
                console.log("Failed to query for users: "+ err)
                res.sendStatus(500)
                res.end()
            } else { 
                workout["sets"] = setsRows  
                getExercisesFromSets(workout).then(() => callback())
            }
        });
    }, function (err) {
        if (err) console.log(err.message);
        //do whatever you want with the final workouts array here
    });
};

function getExercisesFromSets(sets) {
    return new Promise((fulfill, reject) => {
        const selectExercisesQuery = "SELECT id, ex_time, type, ex_id FROM user_exercises WHERE setsFKEY = ?"
        const allSets = sets["sets"]
        async.forEachOf(allSets, function (set, key, callback) {
            const setId = set.id
            getConnection().query(selectExercisesQuery,[setId], (err, exercisesRows, result)=> {
                if (err) {
                    console.log("Failed to query for users: "+ err)
                    res.sendStatus(500)
                    res.end()
                } else {
                    console.log("add exercise")
                    set["exercises"] = exercisesRows
                    callback()
                }
            });
        }, function(err) {
            if (err) console.log(err.message)
            console.log("ENDED")
            console.log(sets)
            fulfill()
        }); 
    }); 
};