所以我的代码是这样的:
router.get('/myapi/someotherapi/:id', (request, response) => {
console.log('api: GET /admin/myapi/someotherapi/:id');
console.log('Reject star redeem requests by id');
auth.verifyToken(request, response, { role: 'Admin' }).then(b_tokenValidated => {
if (b_tokenValidated && b_tokenValidated.statusCode !== 401) {
const myId = b_tokenValidated.userId;
const updateLastActive = user.updateLastActive(myId, request);
const mySpecialFunction = myLib.mySpecialFunction(
request.params.id, myId
);
updateLastActive.then(() => {
mySpecialFunction.then(r => {
generalApiResponseSender(response, r);
})
.catch((err) => {
console.log('mySpecialFunction failed: ', err);
generalApiErrorHandler(response, err);
})
})
.catch((err) => {
generalApiErrorHandler(response, err);
})
}
else {
generalApiErrorHandler(
response,
{
status: 401,
message: "You haven't logged in or token has expired."
}
)
}
}).catch((err) => {
console.log('verifyToken failed: ', err);
let errCode = 401;
let errMsg = "You haven't logged in or token has expired.";
if (typeof err === 'number') {
errCode = err;
errMsg = "Please see error code for more details.";
}
generalApiErrorHandler(
response,
{
status: errCode,
message: errMsg
}
)
})
})
export const generalApiErrorHandler = (response, err) => {
if (!response.headersSent) {
if (err['status'] && err['message']) {
response.status(err['status']).send(err['message']);
}
else if (typeof err === 'number') {
response.sendStatus(err);
}
else {
response.sendStatus(500);
}
}
}
export const generalApiResponseSender = (response, data) => {
if (!response.headersSent) {
if (typeof data !== "number") {
response.send(snake2Camel(data));
}
else {
response.sendStatus(data);
}
}
}
我收到这样的错误:
api: GET /myapi/someotherapi/:id
My function is triggered
id: 30
myId: 1
Request not found, abort.
update_query failed, error: 404
mySpecialFunction failed: 404
api: GET /myapi/someotherapi/:id
My function is triggered
id: 30
myId: 1
Request not found, abort.
update_query failed, error: 404
node:internal/process/promises:246
triggerUncaughtException(err, true /* fromPromise */);
^
[UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "404".] {
code: 'ERR_UNHANDLED_REJECTION'
}
可以看到,这两个调用是完全一样的
第一次调用正常触发错误处理程序,并将错误代码发送回前端。
然而,第二次调用声明没有错误处理程序来处理它,因此它选择停止整个应用程序。
任何人都可以向我解释为什么会发生这种情况,我该如何预防?第二次没有被catch函数捕捉到的错误可能是什么原因?
我想使用 return 而不是 throw 可能会解决这个问题,因为我定义了 404 错误。但我不认为最好的做法是返回错误代码,就像它不是错误而是有效的返回值一样。
附言。我发现有人说
async
不会与 catch 一起工作(UnhandledPromiseRejection 尽管捕捉到了期望),所以我从函数中删除了所有 async
和 await
。然而,这仍然发生。
更新(22/4/2023):
感谢@Konrad,应用程序现在不会自行停止。我得到的新日志如下:
api: GET /myapi/someotherapi/:id
My function is triggered
id: 30
myId: 1
Nothing is updated, abort.
update_query failed, error: 404
Unhandled Rejection at: Promise Promise { <rejected> 404 } reason: 404
(node:21136) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 5)
此外,前端仍然按预期收到 404 状态,这意味着错误一定是正确抛出的,只是 Node.js 未能发现。
您的问题是
updateLastActive
和 mySpecialFunction
都是您同时创建的承诺,并且两者都可能拒绝 - 但您只处理其中一个错误。
你应该写任一个
const myId = b_tokenValidated.userId;
Promise.all([
user.updateLastActive(myId, request),
myLib.mySpecialFunction(request.params.id, myId),
]).then(([_, result]) => {
generalApiResponseSender(response, result);
}, (err) => {
generalApiErrorHandler(response, err);
});
或
const myId = b_tokenValidated.userId;
user.updateLastActive(myId, request).then(() => {
myLib.mySpecialFunction(request.params.id, myId).then((result) => {
generalApiResponseSender(response, result);
})
.catch((err) => {
console.log('mySpecialFunction failed: ', err);
generalApiErrorHandler(response, err);
})
})
.catch((err) => {
generalApiErrorHandler(response, err);
})
或
const myId = b_tokenValidated.userId;
user.updateLastActive(myId, request).then(() => {
return myLib.mySpecialFunction(request.params.id, myId).catch(err => {
console.log('mySpecialFunction failed: ', err);
throw err;
});
}).then(result => {
generalApiResponseSender(response, result);
}, err => {
generalApiErrorHandler(response, err);
});