我对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}}
任何帮助都将不胜感激。干杯
答案 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状态不会拒绝。
即使响应是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'
。