我有一个/ 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
答案 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.forEachOf
(getExercisesFromSets()
中的那个)使用承诺。并且只有在异步完成后,即在错误检查之后,承诺才会得到履行。然后只有在第二个函数被调用并且它完成了承诺(即在 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()
});
});
};