是否需要承诺中的嵌套捕获?

Are nested catches within promises required?

我们想减少 promise 中的 catch 块的数量。如果我们删除嵌套的 catch,异常会冒泡到父 catch 吗?

temporaryUserModel.findOne({email: req.body.email})
    .then(tempUser => {
        if (tempUser) {
            temporaryUserModel.findOneAndUpdate({_id: tempUser.toJSON()._id}, user)
                .then((doc) => {
                    return res.status(200).json({
                        status: 'Success',
                        data: {url: planOpted.chargifySignupUrl}
                    });
                })
                .catch(err => error(err, res));
        } else {
            temporaryUserModel(user).save()
                .then((doc) => {
                    return res.status(200).json({
                        status: 'Success',
                        data: {url: planOpted.chargifySignupUrl}
                    });
                })
                .catch(err => error(err, res));
        }
    })
    .catch(err => error(err, res));

我们想删除两个嵌套的卡扣,只保留底部的卡扣。这样可以吗?

不,他们不会。如果您 链接 您的承诺,它们只会冒泡到结果承诺,为此您需要 return 回调创建的内部承诺。否则外在的 promise 不能等待他们并且不会知道 when/how 他们解决了(无论他们是履行还是拒绝)。

temporaryUserModel.findOne({email: req.body.email}).then(tempUser => {
    if (tempUser) {
        return temporaryUserModel.findOneAndUpdate({_id: tempUser.toJSON()._id}, user);
//      ^^^^^^
    } else {
        return temporaryUserModel(user).save();
//      ^^^^^^
    }
}).then((doc) => {
// no need to duplicate this code when you chain anyway
    return res.status(200).json({
        status: 'Success',
        data: {url: planOpted.chargifySignupUrl}
    });
}).catch(err => error(err, res));

您可以将一些逻辑提取到单独的函数中,return 内部承诺将任何异常冒泡到承诺链中:

temporaryUserModel.findOne({email: req.body.email})
  .then(updateTempUser)
  .then(formatResponse)
  .catch(err => error(err, res));

function updateTempUser(tempUser) {
  if (tempUser) {
    return temporaryUserModel.findOneAndUpdate({
        _id: tempUser.toJSON()._id
    }, user);
  } else {
    return temporaryUserModel(user).save()
  }
}

function formatResponse(doc) {
  return res.status(200).json({
    status: 'Success',
    data: {url: planOpted.chargifySignupUrl}
  });
}