如何避免Promise链中的“已发送标题”?

时间:2017-10-20 11:34:33

标签: javascript node.js express

我正在制作'更改密码'功能。我开始了解有关Promises的更多信息,并提供以下代码:

router.post('/change-password', verifyToken, csrfProtection, (req, res, next) => {
  if (!req.body.password_current || !req.body.password_new) {
    req.flash('info', 'Please fill in both fields.');
    return res.redirect('/change-password');
  }
  const data = {};
  data.password = req.body.password_new;
  tokenHandler.verifyToken(req.cookies.token)
    .then((decoded) => {
      return User.findOne({ '_id.user_id': decoded.user });
    })
    .then((user) => {
      data.userId = ObjectId(user._id.user_id);
      return bcrypt.compare(req.body.password_current, user.password);
    })
    .then((allowed) => {
      if (!allowed) {
        return res.redirect('/change-password');
      }
      console.log('I am not here');
      return User.findOneAndUpdate({ '_id.user_id': data.userId }, { password: data.password }, { new: true });
    })
    .then(() => {
      return res.redirect('/change-password');
    })
    .catch((err) => {
      return next(err);
    });
});

我喜欢Promise如何阻止'回调地狱'。问题是我收到了“已发送标头”错误。我知道这是因为我无法逃脱链并且它保存了所有结果(除非你抛出一个错误)。为了解决这个问题,我使用了以下内容:

router.post('/change-password', verifyToken, csrfProtection, (req, res, next) => {
  if (!req.body.password_current || !req.body.password_new) {
    req.flash('info', 'Please fill in both fields.');
    return res.redirect('/change-password');
  }
  const data = {};
  data.password = req.body.password_new;
  tokenHandler.verifyToken(req.cookies.token)
    .then((decoded) => {
      User.findOne({ '_id.user_id': decoded.user }).then((user) => {
        data.userId = ObjectId(user._id.user_id);
        bcrypt.compare(req.body.password_current, user.password).then((allowed) => {
          if (!allowed) {
            return res.redirect('/change-password');
          }
          User.findOneAndUpdate({ '_id.user_id': data.userId }, { password: data.password }).then((doc) => {
            console.log(doc);
            return res.redirect('/change-password');
          });
        });
      });
    });
});

问题是:是否有更好的解决方案来修复“已发送标头”错误。因为我觉得我的解决方案实际上离“回调地狱”结构只有几步之遥。

2 个答案:

答案 0 :(得分:1)

你可以像这样重写它

then

您可以在var api = revapi1; // the one refers to the slider id var height_left = jQuery(window).height()-jQuery('.navbar').height(); var sliderSettings = api.data('opt') || api[0].opt; console.log(sliderSettings); // here u can see slider revapi1's settings sliderSettings.height = height_left; sliderSettings.conh = height_left; sliderSettings.ulh = height_left; sliderSettings.gridheight[0] = height_left; 函数中返回承诺链。

答案 1 :(得分:0)

根据您的Node版本,您也可以使用async / await重写它。它通常使事情更容易推理。

router.post('/change-password', verifyToken, csrfProtection, async (req, res, next) => {
if (!req.body.password_current || !req.body.password_new) {
    req.flash('info', 'Please fill in both fields.');
    return res.redirect('/change-password');
}

try {
    const data = {};
    data.password = req.body.password_new;
    const decoded = await tokenHandler.verifyToken(req.cookies.token);
    const user = await User.findOne({ '_id.user_id': decoded.user });
    data.userId = ObjectId(user._id.user_id);
    const allowed = await bcrypt.compare(req.body.password_current, user.password);
    if (!allowed) {
        return res.redirect('/change-password');
    } else {
        await User.findOneAndUpdate({ '_id.user_id': data.userId }, { password: data.password }, { new: true });
    }
    return res.redirect('/change-password');
} catch (err) {
    return next(err);
}
});

您需要Node.js> = 7才能使用async / await。