Mongoose Promise在处理错误时打破了链条

时间:2017-11-02 00:27:17

标签: node.js mongodb mongoose promise bluebird

编辑2018-01-18:使用async / await而不是promise chaining。它将解决您的所有问题。

我在NodeJS中有mongoose的代码

    User.find({ name: 'John' })
      .then((users) => {
        if (!users.length) return res.send('No users found.');
        return Request.find({ cost: 100 })
      })
      .then((requests) => {
        console.log('should not get here');
        return res.json(requests);
      })
      .catch((err) => {
        res.status(500).json(err);
      })

如果找不到用户,我希望停止执行,只发送“找不到用户”。没有执行任何其他事情。

我知道我可以改用throw res.send('No users found.');

然后这会使我无法捕捉到真正的错误 - 例如在保存或更新时可能发生的错误 - 并对其进行管理。

我该如何处理?我应该使用不同的代码结构吗?我喜欢这种结构的简单性和可维护性,除了这个缺点。

1 个答案:

答案 0 :(得分:1)

您可以在ES2015 / 6中扩展错误类

class ExtendedError {
  constructor(message){
    super(message)
    this.name = this.constructor.name
    this.message = message
    if (typeof Error.captureStackTrace === 'function'){
      Error.captureStackTrace(this, this.constructor)
    } else {
      this.stack = (new Error(message)).stack
    }
  }
}

class NotFoundError extends ExtendedError {
   constructor(message, options){
     super(message)
     this.status = 404
     this.code = 'NF0001'
   }
}

然后,您的错误处理代码可以查看错误中的更多元数据,以便做出有关如何响应的决定。

User.find({ name: 'John' })
  .then((users) => {
    if (!users.length) throw new NotFoundError('No users found.')        
    return Request.find({ cost: 100 })
  })
  .then((requests) => {
    console.log('should not get here')
    return res.json(requests);
  })
  .catch((err) => {
    let status = err.status || 500
    res.status(500).json({ error: err })
  })

您可能希望创建一个通用的快速API请求/响应处理程序,这样您就不会为每个处理程序重复响应和错误处理。然后处理程序代码只需要返回数据或抛出错误。

User.find({ name: 'John' })
  .then((users) => {
    if (!users.length) throw new NotFoundError('No users found.')        
    return Request.find({ cost: 100 })
  })