Knexjs 和 es6 Try/Catch 导致未处理的承诺拒绝警告?
Knexjs and es6 Try/Catch causing an Unhandled Promise Rejection Warning?
我一直在开发一个使用 PostgreSQL 和 Knexjs 作为查询构建器的新应用程序,但是 运行 遇到了一个我不确定如何处理的问题。
我有一个路由处理程序,如下所示:
export const getSingleUser = async(req, res) => {
let respObj = {
status: 'fail',
message: 'User does not exist'
};
try {
const user = await knex('users').where('id', req.params.id).first();
if (!user) {
res.send(respObj);
}
respObj = {
status: 'success',
data: user
};
res.send(respObj);
} catch(e) {
res.send(respObj);
}
};
效果很好,直到我将一个不存在的用户 ID 混入其中。我假设如果没有为查询找到用户,catch 语句将处理错误,但这似乎不起作用,它只是在 try 块中吐出 respObj
。所以我添加了一个 if 语句来检查用户对象是否不存在,那是我收到以下警告的时候:
(node:25711) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at validateHeader (_http_outgoing.js:503:11)
at ServerResponse.setHeader (_http_outgoing.js:510:3)
at ServerResponse.header (/Users/munsterberg/Sites/fullstack_workspace/esports-manager/services/project/node_modules/express/lib/response.js:767:10)
at ServerResponse.send (/Users/munsterberg/Sites/fullstack_workspace/esports-manager/services/project/node_modules/express/lib/response.js:170:12)
at ServerResponse.json (/Users/munsterberg/Sites/fullstack_workspace/esports-manager/services/project/node_modules/express/lib/response.js:267:15)
at ServerResponse.send (/Users/munsterberg/Sites/fullstack_workspace/esports-manager/services/project/node_modules/express/lib/response.js:158:21)
at _callee3$ (/Users/munsterberg/Sites/fullstack_workspace/esports-manager/services/project/src/controllers/userController.js:45:7)
at tryCatch (/Users/munsterberg/Sites/fullstack_workspace/esports-manager/services/project/node_modules/regenerator-runtime/runtime.js:65:40)
at Generator.invoke [as _invoke] (/Users/munsterberg/Sites/fullstack_workspace/esports-manager/services/project/node_modules/regenerator-runtime/runtime.js:303:22)
at Generator.prototype.(anonymous function) [as next] (/Users/munsterberg/Sites/fullstack_workspace/esports-manager/services/project/node_modules/regenerator-runtime/runtime.js:117:21)
at step (/Users/munsterberg/Sites/fullstack_workspace/esports-manager/services/project/src/controllers/userController.js:14:191)
at /Users/munsterberg/Sites/fullstack_workspace/esports-manager/services/project/src/controllers/userController.js:14:361
at <anonymous>
(node:25711) UnhandledPromiseRejectionWarning: Unhandled promise rejection. 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(). (rejection id: 1)
(node:25711) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
任何人都可以提供更多信息来说明为什么会发生这种情况,解决方法是什么?
解决方法
如果用户不存在,则在 try
块中发送两次响应。这解释了引发的错误:
"Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client".
引发未处理的承诺拒绝警告,因为如果 catch
代码块中的 res.send()
调用抛出,调用 getSingleUser
返回的承诺将被拒绝并出现相同的错误 -暗示返回的承诺没有错误处理(因为不应该被拒绝)。
通过抛出错误将“用户不存在”的情况定向到 catch 块,这可能是一种从一开始就避免该问题的变通方法。缩减示例:
export const getSingleUser = async(req, res) => {
try {
const user = await knex('users').where('id', req.params.id).first();
if (!user) {
throw new Error(" user does not exist");
}
res.send( {
status: 'success',
data: user
});
} catch(e) {
// console.log(e); // debug if needed
res.send( {
status: 'fail',
message: 'User does not exist'
});
}
};
我一直在开发一个使用 PostgreSQL 和 Knexjs 作为查询构建器的新应用程序,但是 运行 遇到了一个我不确定如何处理的问题。
我有一个路由处理程序,如下所示:
export const getSingleUser = async(req, res) => {
let respObj = {
status: 'fail',
message: 'User does not exist'
};
try {
const user = await knex('users').where('id', req.params.id).first();
if (!user) {
res.send(respObj);
}
respObj = {
status: 'success',
data: user
};
res.send(respObj);
} catch(e) {
res.send(respObj);
}
};
效果很好,直到我将一个不存在的用户 ID 混入其中。我假设如果没有为查询找到用户,catch 语句将处理错误,但这似乎不起作用,它只是在 try 块中吐出 respObj
。所以我添加了一个 if 语句来检查用户对象是否不存在,那是我收到以下警告的时候:
(node:25711) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at validateHeader (_http_outgoing.js:503:11)
at ServerResponse.setHeader (_http_outgoing.js:510:3)
at ServerResponse.header (/Users/munsterberg/Sites/fullstack_workspace/esports-manager/services/project/node_modules/express/lib/response.js:767:10)
at ServerResponse.send (/Users/munsterberg/Sites/fullstack_workspace/esports-manager/services/project/node_modules/express/lib/response.js:170:12)
at ServerResponse.json (/Users/munsterberg/Sites/fullstack_workspace/esports-manager/services/project/node_modules/express/lib/response.js:267:15)
at ServerResponse.send (/Users/munsterberg/Sites/fullstack_workspace/esports-manager/services/project/node_modules/express/lib/response.js:158:21)
at _callee3$ (/Users/munsterberg/Sites/fullstack_workspace/esports-manager/services/project/src/controllers/userController.js:45:7)
at tryCatch (/Users/munsterberg/Sites/fullstack_workspace/esports-manager/services/project/node_modules/regenerator-runtime/runtime.js:65:40)
at Generator.invoke [as _invoke] (/Users/munsterberg/Sites/fullstack_workspace/esports-manager/services/project/node_modules/regenerator-runtime/runtime.js:303:22)
at Generator.prototype.(anonymous function) [as next] (/Users/munsterberg/Sites/fullstack_workspace/esports-manager/services/project/node_modules/regenerator-runtime/runtime.js:117:21)
at step (/Users/munsterberg/Sites/fullstack_workspace/esports-manager/services/project/src/controllers/userController.js:14:191)
at /Users/munsterberg/Sites/fullstack_workspace/esports-manager/services/project/src/controllers/userController.js:14:361
at <anonymous>
(node:25711) UnhandledPromiseRejectionWarning: Unhandled promise rejection. 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(). (rejection id: 1)
(node:25711) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
任何人都可以提供更多信息来说明为什么会发生这种情况,解决方法是什么?
解决方法
如果用户不存在,则在 try
块中发送两次响应。这解释了引发的错误:
"Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client".
引发未处理的承诺拒绝警告,因为如果 catch
代码块中的 res.send()
调用抛出,调用 getSingleUser
返回的承诺将被拒绝并出现相同的错误 -暗示返回的承诺没有错误处理(因为不应该被拒绝)。
通过抛出错误将“用户不存在”的情况定向到 catch 块,这可能是一种从一开始就避免该问题的变通方法。缩减示例:
export const getSingleUser = async(req, res) => {
try {
const user = await knex('users').where('id', req.params.id).first();
if (!user) {
throw new Error(" user does not exist");
}
res.send( {
status: 'success',
data: user
});
} catch(e) {
// console.log(e); // debug if needed
res.send( {
status: 'fail',
message: 'User does not exist'
});
}
};