Knexjs和es6尝试/捕获导致未处理的承诺拒绝警告?

时间:2018-01-30 22:28:47

标签: javascript node.js postgresql knex.js

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

任何人都可以提供有关这种情况发生原因的更多信息,并解决了哪些问题?

1 个答案:

答案 0 :(得分:1)

解决方法

如果用户不存在,则会在try块中发送两次响应。据推测,这可以间接解释所引起的错误:

  

&#34;错误[ERR_HTTP_HEADERS_SENT]:无法在将标题发送到客户端后设置标题&#34;。

重定向&#34;用户不存在&#34;通过抛出错误来捕获块的情况可能是一个解决问题的方法。一个简单的例子:

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块产生未被捕获的承诺拒绝错误对我来说很突出。也许res.send被编码为在发生错误的情况下做一些不寻常的事情,比如通过异步提出被拒绝的承诺,但不幸的是,这只是我自己的推测,而真正的原因可能完全不同。