node.js - UnhandledPromiseRejectionWarning:TypeError:无法读取未定义的属性“roleId”
问题描述
我有一个要求,要求我验证用户是否选择了正确的经理。它们之间的关联是各自所属的组 id。一个用户可以与一个组 id 相关联,一个管理员可以与多个组 id 相关联。当允许用户选择他的经理时,我需要验证用户的组 ID 是否存在于经理的组 ID 列表中。这是我在下面实现的代码,但我得到UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'roleId' of undefined
我的路由文件 account.ts 有以下代码块
let promise = accountController.update(user);
promise.then(function(data) {
if (data.IsSuccessful == true)
{
result.IsSuccessful = true;
result.SuccessMessage = process.env.USER_UPDATED || "User changed";
return res.status(200).json(result);
}
else
{
result.IsSuccessful = false;
result.ReasonForFailure = data.ReasonForFailure;
res.status(200).json(result);
}
}).catch(function(err){
result.IsSuccessful = false;
result.ReasonForFailure = err.message;
res.status(200).json(result);
});
我的控制器文件 account.ts 具有以下更新方法的代码块
update = (account: Account) : Promise<Result<Account>> => {
var thisObj = this;
return new Promise<Result<Account>>(function (resolve, reject){
let result = new Result<Account>();
result.Data = account;
MongoClient.connect(config.database.uri, { useUnifiedTopology: true } , async function(err: any, db: any) {
if (err) {
// throw err;
result.IsSuccessful = false;
result.ReasonForFailure = err.message;
reject(result);
}
var dbo = db.db(config.database.name);
var newvalues = { $set:
{
name: account.name,
title: account.title,
organization: account.organization,
reportingTo: account.reportingTo,
workNumber: account.workNumber,
mobileNumber: account.mobileNumber,
allowNotification: account.allowNotification,
allowEmail: account.allowEmail,
groups: account.groups,
updatedDate: account.updatedDate,
isProfileSetupComplete: true,
photo:account.photo
}
};
let existingUser: any;
var query = {email:account.email};
var resultArray = await dbo.collection("users").find(query).toArray();
if (resultArray.length > 0) {
existingUser = resultArray[0];
} else {
db.close();
result.ReasonForFailure = process.env.INVALID_USER_ID || "Invalid User Id";
result.IsSuccessful = false;
reject(result);
}
console.log(existingUser);
if (existingUser.roleId == "1") { //roleId="1" means user
//validate manager id. reportingTo id must be a manager
var queryReporting = { _id: account.reportingTo };
let managerUser: any;
var resultManagerArray = await dbo.collection("users").find(queryReporting).toArray();
if (resultManagerArray.length > 0) {
console.log("managerUser in");//<--This is not printing in the console log
managerUser = resultManagerArray[0];
} else {
db.close();
result.ReasonForFailure = "Invalid reporting id.";// process.env.INVALID_USER_ID || "Invalid User Id";
result.IsSuccessful = false;
resolve(result);
}
//validate manager user
console.log("managerUser out");
console.log(managerUser);
if (managerUser.roleId !== "2"){//<--UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'roleId' of undefined
result.IsSuccessful = false;
result.ReasonForFailure = "Reporting to must be a Manager";
reject(result);
}
//manager and user must be associated with same group
if (!managerUser.groups.includes(account.groups)) {
result.IsSuccessful = false;
result.ReasonForFailure = "Incorrect Manager selection. Employee must be associated with a group the manager is associated with."
reject(result);
}
}
dbo.collection("users").updateOne(query, newvalues, function(err: any, resultSet: any) {
if (err) {
//throw err;
db.close();
result.IsSuccessful = false;
result.ReasonForFailure = err.message;
reject(result);
} else {
result.SuccessMessage = oldImage;
result.IsSuccessful = true;
db.close();
resolve(result);
}
});
});
});
}
上面代码中的 managerUser.roleId !== "2" 是我得到UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'roleId' of undefined
我在第一次调用 find 查询时放了 await ,它按预期工作,等待调用完成,但下一次 await 似乎没有效果。执行没有等待调用完成。
你能帮助我在这里缺少什么吗?
谢谢,赫曼特。
解决方案
在所有/调用之后,您可能缺少return
语句。与and不同,它们是普通的函数调用,不会终止函数的执行。resolve(result);
reject(result);
return
throw
此外,您不应将 anasync function
作为回调传递给不处理返回的承诺的函数。你应该只承诺connect
单独的调用,等待它的结果,然后await
在回调之后或then
回调中继续你的函数的其余部分,以确保正确处理错误。
update = async (account: Account) : Promise<Result<Account>> => {
let result = new Result<Account>();
result.Data = account;
try {
const db = await MongoClient.connect(config.database.uri, { useUnifiedTopology: true });
try {
const dbo = db.db(config.database.name);
const newvalues = {
$set: {
name: account.name,
title: account.title,
organization: account.organization,
reportingTo: account.reportingTo,
workNumber: account.workNumber,
mobileNumber: account.mobileNumber,
allowNotification: account.allowNotification,
allowEmail: account.allowEmail,
groups: account.groups,
updatedDate: account.updatedDate,
isProfileSetupComplete: true,
photo:account.photo
}
};
var resultArray = await dbo.collection("users").find({email: account.email}).toArray();
if (resultArray.length == 0) {
result.ReasonForFailure = process.env.INVALID_USER_ID || "Invalid User Id";
result.IsSuccessful = false;
return result;
}
const existingUser = resultArray[0];
console.log(existingUser);
if (existingUser.roleId == "1") {
var resultManagerArray = await dbo.collection("users").find({ _id: account.reportingTo }).toArray();
if (resultManagerArray.length == 0) {
result.ReasonForFailure = "Invalid reporting id.";// process.env.INVALID_USER_ID || "Invalid User Id";
result.IsSuccessful = false;
return result;
}
console.log("managerUser in");
const managerUser = resultManagerArray[0];
console.log("managerUser out");
console.log(managerUser);
if (managerUser.roleId !== "2") {
result.IsSuccessful = false;
result.ReasonForFailure = "Reporting to must be a Manager";
return result;
}
//manager and user must be associated with same group
if (!managerUser.groups.includes(account.groups)) {
result.IsSuccessful = false;
result.ReasonForFailure = "Incorrect Manager selection. Employee must be associated with a group the manager is associated with."
return result;
}
}
const resultSet = await dbo.collection("users").updateOne(query, newvalues);
result.SuccessMessage = oldImage;
result.IsSuccessful = true;
return result;
} finally {
db.close()
}
} catch(err) {
result.IsSuccessful = false;
result.ReasonForFailure = err.message;
return result;
}
};