javascript - NodeJS等待/异步使数据检索同步
问题描述
我知道这已经问了数千次了,但我仍然无法找到答案。我有一个 forEach 循环,用于循环遍历用户列表并检索每个用户的特定位置数据。在 forEach 中,第一个函数调用获取分支,然后第二个函数调用获取该分支的信息。
问题是 forEach 循环在从函数返回数据之前没有完成,这会导致各种问题。
这是我的代码:
//getAllUserData() - this is the function which returns prematurely
const getAllUserData = async () => {
const sequelize = DB.GetDB('mcaintranet');
const userDB = MCAIntranet.initModels(sequelize);
userDB.tblUsers.belongsTo(userDB.tblSMSSent, { foreignKey: 'collector', targetKey: 'user' });
userDB.tblSMSSent.hasMany(userDB.tblUsers);
let users = await userDB.tblUsers.findAll({
attributes: ['collector', 'id'],
include: {
model: userDB.tblSMSSent,
attributes: [[sequelize.fn('COUNT', 'tblSMSSent.id'), 'numMessages']]
},
raw: true,
group: ['collector', 'tblUsers.id'],
})
//return list of all users and texts sent
//UserName, User Province Code, # Messages Sent, user Number
try {
await users.forEach(async user => {
const branch = await Users.getUserBranch(user);
const province = getKey(branch);
user.province = province;
// console.log("User: ", [user, branch])
//clean up JSON from join results
user.numMessages = user["tblSMSSent.numMessages"];
delete user["tblSMSSent.numMessages"];
})
const obj = { 'users': users };
console.log("DONE: ", obj)
return obj;
}
catch (ex) {
console.log("ERROR: ", ex)
const msg = ex.Message;
return { results: "False", message: "SMS.js 61" + msg }; //is user allowed to use SMS page)
}
}
//getUserBranch() - accessor function to return branch number
const getUserBranch = async (user) => {
// console.log("Branch User: ", user)
let branch = getUserProps(user.collector ? user.collector : user, 'branch');
// console.log(props)
if (!branch) branch = 0;
return branch;
}
//getUserProps - pulls all user properties from database and filters as necessary
const getUserProps = async (user, propName = null) => {
let ret = {};
if (user.collector) user = user.collector;
user = user.trim();
let filter = {
collector: user
}
if (propName) {
filter.propertyName = propName
}
// console.log("Filter: ", filter)
const sequelize = DB.GetDB('MCAIntranet');
const propsDB = MCAIntranet.initModels(sequelize);
//get all values contained for user
let props = await propsDB.tblUserProperties.findAll({
attributes: ['id', 'propertyName', 'propertyValue', 'updated'],
where: filter,
order: [['updated', 'DESC']],
})
// console.log("Props: ", props);
let distinctProps = await propsDB.tblUserProperties.findAll({
attributes: ['propertyName'],
DISTINCT: true,
where: filter,
})
//the SMS Credits item is sometimes added as a second row
//so loop through all potential value rows for user
distinctProps.forEach(dr => {
// console.log(dr);
var name = dr.propertyName.toLowerCase();
// console.log("name: ", name)
try {
//get individual values for each property user possesses
let tmpRows = props.filter(row => row.propertyName.toLowerCase() == name);
// console.log("tmpRows: ", tmpRows)
//get the most recent value
let row = tmpRows[tmpRows.length - 1];
var item = row.propertyName.trim();
var value = row.propertyValue.trim();
//add to returned JSON
ret[item] = value;
} catch (ex) {
console.log("USERS.js 157 " + ex.message);
return ({ error: "USERS.js 158" + ex.Message });
}
})
// console.log("Ret: ", ret)
return ret;
}
//getKey() - returns necessary data about the user province
const getKey = (data) => {
let branch;
try {
branch = data.branch ? data.branch : data;
}
catch (ex) {
console.log(data)
console.log(ex)
}
branch = parseInt(branch);
// console.log(branch)
try {
let acctKey = "";
let province = "";
let abbr = "";
// console.log("Branch: ", branch)
switch (branch) {
case 4: //vancouver
case '4':
abbr = "BC";
acctKey = key["BC"];
province = "British Columbia";
break;
case 7: //Montreal
case '7':
abbr = "QC";
acctKey = key["QC"];
province = "Quebec";
break;
case 9: //Toronto
case '9':
abbr = "ON";
acctKey = key["ON"];
province = "Ontario";
break;
default: //Edmonton
abbr = "AB";
acctKey = key["AB"];
province = "Alberta";
break;
}
return { key: acctKey, province: province, abbr: abbr };
}
catch (ex) {
throw ex;
}
}
在等待和异步的集合中的某个地方缺少某些东西,导致 getAllData() 函数返回没有位置数据的用户名。在获得所有数据之前,如何阻止执行?请忽略我在努力解决这个问题时所付出的额外等待。
谢谢。
解决方案
而不是forEach
,你想要这个:
await Promise.all(users.map(async (user) => {...}))
map 返回每个内部操作的承诺,并且await
-ing Promise.all
等待所有这些承诺完成