【问题标题】:Knexjs and es6 Try/Catch causing an Unhandled Promise Rejection Warning?Knexjs 和 es6 Try/Catch 导致未处理的承诺拒绝警告?
【发布时间】:2018-07-09 22:30:15
【问题描述】:

我一直在开发一个使用 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.

谁能提供更多关于为什么会发生这种情况以及解决方法的信息?

【问题讨论】:

    标签: javascript node.js postgresql knex.js


    【解决方案1】:

    解决方法

    如果用户不存在,则会在 try 块中发送两次响应。这解释了引发的错误:

    “错误 [ERR_HTTP_HEADERS_SENT]:在将标头发送到客户端后无法设置标头”。

    未处理的 Promise 拒绝警告正在引发,因为如果 catch 代码块中的 res.send() 调用抛出,从调用 getSingleUser 返回的 Promise 将被拒绝并出现相同的错误 - 这意味着没有适当的错误处理对于返回的承诺(因为不应该被拒绝)。

    通过抛出错误将“用户不存在”的情况引导到 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'
        });
      }
    };
    

    【讨论】:

    • 完美的解释。我对 try/catch 块缺乏了解是问题所在。非常感谢:)
    猜你喜欢
    • 2021-08-02
    • 2020-01-01
    • 2020-08-20
    • 1970-01-01
    • 2018-07-02
    • 1970-01-01
    相关资源
    最近更新 更多