猫鼬.catch块在多个地方都相同。如何避免这种情况?

时间:2019-07-03 10:57:16

标签: javascript node.js mongoose

我在Node REST api中使用猫鼬诺言,并且我有很多相同的.catch块。

这是一条小路:

router.get('/', (req, res) => {
    Post.find()
        .populate('category', 'name')
        .exec()
        .then(posts => {
            res.status(200).json(posts);
        })
        .catch(err => {
            log.error(err);
            res.status(500).json(err);
        });
});

我有一些路由,在同一函数中,确切的.catch块会出现3次。 我可以在其中创建日志和结果的函数,然后将该函数传递给.catch吗?还是可以使用一些中间件?我该如何清理我的代码?

这里是一团糟:

router.delete('/:commentId', checkAuth, (req, res) => {
    // Find the comment
    Comment.findById(req.params.commentId).exec()
        .then(comment => {
            foundComment = comment;

            // Delete the comment
            Comment.deleteOne({ _id: req.params.commentId }).exec()
                .then(result => {
                    if (result.deletedCount) {

                        // If the comment has replies, remove them as well
                        if (foundComment.replies.length > 0) {
                            Comment.deleteMany({ _id: { $in: foundComment.replies } }).exec()
                                .then(result => {
                                    if (result.deletedCount) {
                                        res.status(200).json({
                                            deletedCount: result.deletedCount + 1
                                        });
                                    }
                                })
                                .catch(err => {
                                    log.error(err);
                                    res.status(500).json(err);
                                });

                            return;
                        }

                        res.status(200).json({
                            deletedCount: result.deletedCount
                        });
                    } else {
                        res.status(404).json({
                            message: `Comment with id ${req.params.commentId} doesn't exist.`
                        });
                    }
                })
                .catch(err => {
                    log.error(err);
                    res.status(500).json(err);
                });

        })
        .catch(err => {
            log.error(err);
            res.status(500).json(err);
        });
});

3 个答案:

答案 0 :(得分:2)

返回Promise链中的每个Promises,以便将它们都绑在一起,使您可以在最后放置一个.catch,如果里面有任何东西,它将运行:

router.delete('/:commentId', checkAuth, (req, res) => {
  let foundComment;
  Comment.findById(req.params.commentId).exec()
    .then(comment => {
      foundComment = comment;
      return Comment.deleteOne({ _id: req.params.commentId }).exec();
    })
  .then(result => {
    if (!result.deletedCount) {
      res.status(404).json({
        message: `Comment with id ${req.params.commentId} doesn't exist.`
      });
      return;
    }
    if (foundComment.replies.length <= 0) {
      res.status(200).json({
        deletedCount: result.deletedCount
      });
      return;
    }
    return Comment.deleteMany({ _id: { $in: foundComment.replies } }).exec()
      .then(result => {
      if (result.deletedCount) {
        res.status(200).json({
          deletedCount: result.deletedCount + 1
        });
      }
    });
  })
  .catch(err => {
    log.error(err);
    res.status(500).json(err);
  });
});

通常,如果可以帮助的话,请尽量避免嵌套.then -扁平代码是更具可读性的代码。 async / await将使事情变得更加清晰:

router.delete('/:commentId', checkAuth, async (req, res) => {
  try {
    const foundComment = await Comment.findById(req.params.commentId).exec();
    const deleteOneResult = await Comment.deleteOne({ _id: req.params.commentId }).exec();
    if (!deleteOneResult.deletedCount) {
      res.status(404).json({
        message: `Comment with id ${req.params.commentId} doesn't exist.`
      });
      return;
    }
    if (foundComment.replies.length <= 0) {
      res.status(200).json({
        deletedCount: result.deletedCount
      });
      return;
    }
    const deleteManyResult = await Comment.deleteMany({ _id: { $in: foundComment.replies } }).exec()
    if (deleteManyResult.deletedCount) {
      res.status(200).json({
        deletedCount: deleteManyResult.deletedCount + 1
      });
    }
  } catch (err) {
    log.error(err);
    res.status(500).json(err);
  }
});

答案 1 :(得分:1)

我建议更改您的代码以使用async/await并使用try/catch来处理错误。

router.get('/', async (req, res) => {
    try {
        let posts = await Post.find().populate('category', 'name');
        let comment = await Comment.findById(req.params.commentId);
        if (!comment) {
            return res.status(404).json({
                message: `Comment with id ${req.params.commentId} doesn't exist.`
            });
        }
        // Another query...
        res.status(200).json(posts);
    } catch(err) {
        log.error(err);
        res.status(500).json(err);
    });
});

答案 2 :(得分:0)

您可以将函数直接传递给.catch,例如:

function handleError(err) {
  console.error('the error:', err.message)
}

const promise = new Promise((resolve, reject) => reject(new Error('your error')))

promise.catch(handleError)