处理从回调函数中抛出的错误的正确方法是什么?
What is the proper way of handling errors that are thrown from withing a callback function?
我正在开发一个 NodeJS 应用程序,我正在使用 mongoose 将数据保存到我的 MongoDB 数据库中。
我的控制器可以在 /register
url 处接受一个 POST
请求和一些数据。看起来像这样:
router.post("/register", async (req: Request, res: Response) => {
const accountModel: IRegistrationAccount = {
firstName: req.body.firstName,
lastName: req.body.lastName,
email: req.body.email,
password: req.body.password,
repeatedPassword: req.body.repeatedPassword,
};
try {
registerAccount(accountModel);
res.status(OK).send("Registration successful.");
} catch (err) {
res.status(NOT_ACCEPTABLE).send(err);
}
});
如您所见,我想 return 向用户发送一条错误消息,以便他们确切知道出了什么问题。这是 registerAccount
方法:
export function registerAccount(accountModel: IRegistrationAccount) {
if (accountModel.firstName.length === 0)
throw "Your first name may not be empty.";
if (accountModel.email.length < 3) throw "Your email is too short.";
if (accountModel.password !== accountModel.repeatedPassword)
throw "The passwords You entered don't match.";
if (accountModel.password.length < 8) throw "Your password is too short.";
const account = new Account(accountModel);
account.save(function (err) {
if (err) return logger.err(err);
return logger.info("Created account.");
});
}
当用户输入的数据有问题时,我 return 使用 throw 发出错误消息,然后在控制器中捕获。问题是:我如何知道 save
中的回调函数是否抛出错误以及如何处理该错误?这是我第一次使用 Node,我尝试四处搜索但找不到合适的答案。
我会用 util.promisify 承诺 account
,然后 return Promise 和 .catch
它在调用者中:
return accountSavePromisified().then(() => {
logger.info("Created account.");
});
try {
registerAccount(accountModel)
.then(() => {
res.status(OK).send("Registration successful.");
})
.catch((err) => {
// Catch asynchronous errors (thrown by `.save`):
res.status(NOT_ACCEPTABLE).send(err);
})
} catch (err) {
// Catch synchronous errors (thrown by your validator):
res.status(NOT_ACCEPTABLE).send(err);
}
如果您不关心区分 .save
抛出的错误和验证器抛出的错误,您也可以 await
调用 registerAccount
而不是调用 .then
就可以了。
您还可以考虑通过 returning 来自 registerAccount
的错误字符串而不是抛出,例如 return 'Your first name may not be empty.'
:
const result = registerAccount(accountModel);
if (typeof result === 'string') {
res.status(NOT_ACCEPTABLE).send(result);
return;
}
result.then(() => {
res.status(OK).send("Registration successful.");
})
.catch((err) => {
res.status(NOT_ACCEPTABLE).send(result);
});
save
方法可以 return Promise
所以你根本不需要使用回调:
export async function registerAccount(accountModel: IRegistrationAccount) {
if (accountModel.firstName.length === 0)
throw "Your first name may not be empty.";
if (accountModel.email.length < 3) throw "Your email is too short.";
if (accountModel.password !== accountModel.repeatedPassword)
throw "The passwords You entered don't match.";
if (accountModel.password.length < 8) throw "Your password is too short.";
const account = new Account(accountModel);
await account.save();
}
并在调用此函数的行添加 await
:
try {
await registerAccount(accountModel);
logger.info("Created account.")
res.status(OK).send("Registration successful.");
} catch (err) {
logger.err(err)
res.status(NOT_ACCEPTABLE).send(err);
}
我正在开发一个 NodeJS 应用程序,我正在使用 mongoose 将数据保存到我的 MongoDB 数据库中。
我的控制器可以在 /register
url 处接受一个 POST
请求和一些数据。看起来像这样:
router.post("/register", async (req: Request, res: Response) => {
const accountModel: IRegistrationAccount = {
firstName: req.body.firstName,
lastName: req.body.lastName,
email: req.body.email,
password: req.body.password,
repeatedPassword: req.body.repeatedPassword,
};
try {
registerAccount(accountModel);
res.status(OK).send("Registration successful.");
} catch (err) {
res.status(NOT_ACCEPTABLE).send(err);
}
});
如您所见,我想 return 向用户发送一条错误消息,以便他们确切知道出了什么问题。这是 registerAccount
方法:
export function registerAccount(accountModel: IRegistrationAccount) {
if (accountModel.firstName.length === 0)
throw "Your first name may not be empty.";
if (accountModel.email.length < 3) throw "Your email is too short.";
if (accountModel.password !== accountModel.repeatedPassword)
throw "The passwords You entered don't match.";
if (accountModel.password.length < 8) throw "Your password is too short.";
const account = new Account(accountModel);
account.save(function (err) {
if (err) return logger.err(err);
return logger.info("Created account.");
});
}
当用户输入的数据有问题时,我 return 使用 throw 发出错误消息,然后在控制器中捕获。问题是:我如何知道 save
中的回调函数是否抛出错误以及如何处理该错误?这是我第一次使用 Node,我尝试四处搜索但找不到合适的答案。
我会用 util.promisify 承诺 account
,然后 return Promise 和 .catch
它在调用者中:
return accountSavePromisified().then(() => {
logger.info("Created account.");
});
try {
registerAccount(accountModel)
.then(() => {
res.status(OK).send("Registration successful.");
})
.catch((err) => {
// Catch asynchronous errors (thrown by `.save`):
res.status(NOT_ACCEPTABLE).send(err);
})
} catch (err) {
// Catch synchronous errors (thrown by your validator):
res.status(NOT_ACCEPTABLE).send(err);
}
如果您不关心区分 .save
抛出的错误和验证器抛出的错误,您也可以 await
调用 registerAccount
而不是调用 .then
就可以了。
您还可以考虑通过 returning 来自 registerAccount
的错误字符串而不是抛出,例如 return 'Your first name may not be empty.'
:
const result = registerAccount(accountModel);
if (typeof result === 'string') {
res.status(NOT_ACCEPTABLE).send(result);
return;
}
result.then(() => {
res.status(OK).send("Registration successful.");
})
.catch((err) => {
res.status(NOT_ACCEPTABLE).send(result);
});
save
方法可以 return Promise
所以你根本不需要使用回调:
export async function registerAccount(accountModel: IRegistrationAccount) {
if (accountModel.firstName.length === 0)
throw "Your first name may not be empty.";
if (accountModel.email.length < 3) throw "Your email is too short.";
if (accountModel.password !== accountModel.repeatedPassword)
throw "The passwords You entered don't match.";
if (accountModel.password.length < 8) throw "Your password is too short.";
const account = new Account(accountModel);
await account.save();
}
并在调用此函数的行添加 await
:
try {
await registerAccount(accountModel);
logger.info("Created account.")
res.status(OK).send("Registration successful.");
} catch (err) {
logger.err(err)
res.status(NOT_ACCEPTABLE).send(err);
}