在 promise 中传播 .catch 的正确方法是什么?

What's the proper way to propagate .catch in promise?

我正在使用 bluebird 来 promisify mongoose 库。所以,我目前找到并保存如下数据:

    User.findOneAsync({email: req.body.text})
      .then(function(user) {
        user.saveAsync()
          .spread(function(savedUser){
            res.json(savedUser);
          })
          .catch(function(err) {
            res.json({
              status: 500,
              message: 'foo'
            });
          });
      })
      .catch(function(err) {
         res.json({
           status: 500,
           message: 'foo'
         });
      });

两个catch函数完全相同。这只是一个演示,我在实际工作中有时会出现两个相同的 catch 函数。我可以将 catch 中的函数分离到它自己的函数中。但是,我不得不多次编写 catch 函数。避免重复捕获函数的好方法是什么?任何帮助,将不胜感激。

你实际上可以 return user.saveAsync()。然后你的错误传播到较低的 catch 函数。像那样:

 User.findOneAsync({email: req.body.text})
  .then(function(user) {
    return user.saveAsync()
      .spread(function(savedUser){
        res.json(savedUser);
      });
  })
  .catch(function(err) {
     res.json({
       status: 500,
       message: 'foo'
     });
  });

之所以有效,是因为您的 spread return 是一个 Promise。然后这个承诺沿着外链传递,包括一个可能的错误。在外链中,您可以使用 catch 函数捕获它,该函数现在将捕获来自内链和外链的错误,因为它们已连接。

您还可以通过按照以下方式做一些事情来大大缩短此代码并且没有两个 promise 链:

 User.findOneAsync({email: req.body.text})
 .call("saveAsync")
 .spread(function (savedUser) {
     res.json(savedUser);
 })
 .catch(function(err) {
    res.json({
      status: 500,
      message: 'foo'
    });
 });

这通常被认为是使用 promises 时的良好做法。

你应该避免在 then 成功句柄中嵌套,除非需要。它使您的代码更具可读性,并且您只需使用一个 catch 函数。所有被拒绝的承诺都会传播到最后一个 catch 函数。

User.findOneAsync({email: req.body.text})
    .then(function(user) {
        return user.saveAsync();
    })
    .spread(function(savedUser){
        return res.json(savedUser);
    })
    .catch(function(err) {
        return res.json({
            status: 500,
            message: 'foo'
        });
    });