承诺拒绝不触发

时间:2017-07-23 22:23:04

标签: javascript node.js promise fetch

我对js中的Promises相对较新,并且我很难理解为什么当服务器以401未经授权的方式响应时,下面的代码块没有运行我的catch函数。

function loginUser(email, password) {
  let body = { email: email, password: password  }

  return fetch('http://localhost:3000/api/v1/sessions', {
    method: 'POST',
    body: JSON.stringify(body),
    headers: { 'Content-Type': 'application/json' }
    }).then(response => {
       return response.json().then(json => {
         console.log(response.ok) // false
         return response.ok ? json : Promise.reject(json)
    }).catch(err => {
      console.error(err)
    })
  })
}

loginUser函数:

{{1}}

任何帮助都将不胜感激。干杯

3 个答案:

答案 0 :(得分:3)

来自fetch GitHub:

https://github.com/github/fetch/issues/201

  

Fetch API只有在无法发出请求时才会失败。如果可以,请抓取   即使状态不好,也会成功执行。

所以听起来你的.then(分支会处理401,你需要在这里处理它。

只有在无法提出请求时才会执行

.catch(

答案 1 :(得分:1)



Promise.reject()
  .catch(() => console.log("rejection is caught in first `catch`"))
  .then(() => console.log("`catch` returns fulfilled  promise so `then` is executed"))
  .catch(() => console.log("this won't be executed"))




答案 2 :(得分:0)

我在这里看到几个问题:

首先,来自fetch()的401响应不会拒绝。这是一个成功的http请求。它联系了服务器,发送了请求并得到了响应。您获得401状态的事实取决于您的应用程序如何处理。 401状态不会拒绝。

来自MDN doc for fetch()

  

即使响应是HTTP 404或500,fetch()返回的Promise也不会拒绝HTTP错误状态。相反,它将正常解析(ok状态设置为false),它只会拒绝网络故障或任何事情阻止请求完成。

其次,当你这样做时:

}).catch(err => {
  console.error(err)
})

您正在捕获被拒绝的承诺,处理它并将其转换为已解决的承诺(就像try / catch停止抛出异常一样)。所以你的函数,如所写,永远不会返回被拒绝的承诺)。如果你想这样记录,但保留被拒绝的承诺,那么你需要重新抛出错误:

}).catch(err => {
  console.error(err)
  throw err;
})

如果您希望只有在获得有效数据时才能获得已解决的承诺,您可以专门将承诺拒绝其他状态,或者您可以从fetch中检查response.ok并将其转为拒绝:

function loginUser(email, password) {
  let body = { email: email, password: password  }

  return fetch('http://localhost:3000/api/v1/sessions', {
    method: 'POST',
    body: JSON.stringify(body),
    headers: { 'Content-Type': 'application/json' }
    }).then(response => {
       // make sure that we actually got data
       if (!response.ok) {
          throw new Error(`No response.ok.  Got http status ${response.status}`);
       }
       return response.json().then(json => {
         console.log(response.ok) // false
         return response.ok ? json : Promise.reject(json)
    }).catch(err => {
      console.error(err);
      throw err;
    });
  })
}

第三,由于您所引用的错误是授权错误,因此应警告您fetch()默认情况下不会发送任何Cookie,因此如果您依赖Cookie进行身份验证,则必须配置您的fetch()请求专门用于使用提取选项发送Cookie:credentials: 'include'