即使我返回404,我的承诺的成功块也会一直执行

时间:2016-10-14 04:09:51

标签: node.js http promise es6-promise

当用户使用不正确的电子邮件和密码登录时,即使服务器返回400,我的客户端承诺的成功块仍会执行。

我正在使用Redux和React,所以我正在调用一个动作创建者,它使用axios调用HTTP请求。我需要帮助理解为什么我没有正确处理错误,因为即使我从服务器返回400个状态,我的应用程序的auth函数的其余部分如注册,注销等都表现相同的方式。

这是我从我的组件调用login的地方,成功块总是执行:

handleFormSubmit({
  email, password
}) {
  this.props.loginUser({
    email, password
  }).then(() => {
    toastr.success("You are logged in!");
  }).catch(() => {
    toastr.warning("Could not log in");
  })
}

这是动作创建者“loginUser”,当我从服务器返回400时,此功能的成功块不会运行:

export function loginUser({ email, password }) {

  return function(dispatch) {

    return axios.post(`/users/login`, {
        email, password
      })
      .then(response => {

        dispatch({
          type: AUTH_USER
        });


        localStorage.setItem('token', response.headers['x-auth']);
        browserHistory.push('/feature');
      })
      .catch(() => {
        dispatch(authError('Incorrect email or password'));
      });
  }
}

这是路线'/ users / login'请注意400状态实际上确实返回:

app.post('/users/login', (req, res) => {
  var body = _.pick(req.body, ['email', 'password']);

  User.findByCredentials(body.email, body.password).then(user => {
    return user.generateAuthToken().then(token => {
      res.header('x-auth', token).send(user);
    });
  }).catch(e => {
    res.status(400).send();
  });
});

2 个答案:

答案 0 :(得分:1)

问题出在loginUser函数的catch处理程序中。 如果你想在promise链中更远地捕获错误,你需要在catch块中抛出错误。

  .catch(() => {
      dispatch(authError('Incorrect email or password'));
      throw Error('Incorrect email or password');
  });

答案 1 :(得分:1)

你的问题是,你误解了catch条款在承诺中的含义。

如果它只是一个拒绝处理程序那么你可以想到的方式:

.then(null, function(err) {
  // handle the error
})

意思是只处理来自承诺链的最后一个未处理的错误,无论发生什么事情,你都可以继续链接它。

示例:



new Promise((resolve, reject) => {
  setTimeout(() => reject(Error('After 1 sec')), 1000)
})
.catch((err) => {
  console.log(`catch: ${err}`);
  return 5;
})
.then((five) => {
 // this chains because the error was handled before in the chain
 console.log(`catch.then: ${five}`); // 5
})
.catch(() => {
  console.log('No error happened between this error handler and previous so this is not logged');
});




要使错误从当前catch传播到下一个错误处理程序,您可以返回被拒绝的Promise(或重新抛出错误),以使链跳过所有成功处理程序,直到下一次失败(或catch)处理程序。



new Promise((resolve, reject) => {
  setTimeout(() => reject(Error('After 1 sec')), 1000)
})
.catch((err) => {
  // return a reject promise to propagate to the next error handler
  return Promise.reject(err);
  // can also `throw err;`
})
.then((nothing) => {
 // this doesn't happen now
 console.log(nothing);
})
.catch(console.error); // this logs the error




附注:如果您未在Promise链中提供拒绝处理程序(.then中的第二个参数),则默认拒绝处理程序的行为基本上如下:

function defaultRejectionHandler(err) {
  throw err;
}

这意味着它会重新抛出传递给它的错误,因此错误可以传播到您指定的下一个错误处理程序。