使用 fetch() 处理失败的 HTTP 响应
测验:对网络新fetch()API的调用有什么作用?
fetch("http://httpstat.us/500")
.then(function() {
console.log("ok");
}).catch(function() {
console.log("error");
});
如果你像我一样,你可能会认为这段代码在运行时会记录“错误”——但实际上它会记录“ok”。
这种期望可能来自多年的 jQuery 开发,因为jQuery 的ajax()方法fail
在响应包含失败的 HTTP 状态代码时调用其处理程序。例如,下面的代码在运行时会记录“错误”:
$.ajax("http://httpstat.us/500")
.done(function() {
console.log("ok");
}).fail(function() {
console.log("error");
});
为什么会这样fetch()
工作?
根据 MDN,fetch()
API 仅在遇到“网络错误”时才会拒绝承诺,尽管这通常意味着权限问题或类似问题。” 基本上fetch()
只会在用户离线,或者发生一些不太可能的网络错误,例如 DNS 查找失败时才会拒绝一个 promise。
好消息是fetch
提供了一个简单的ok
标志来指示 HTTP 响应的状态代码是否在成功范围内。例如以下代码记录“错误:内部服务器错误(…)”:
fetch("http://httpstat.us/500")
.then(function(response) {
if (!response.ok) {
throw Error(response.statusText);
}
return response;
}).then(function(response) {
console.log("ok");
}).catch(function(error) {
console.log(error);
});
为了保持此代码干燥和可重用,您可能想要创建一个通用错误处理函数,您可以将其用于所有fetch()
调用。以下代码将错误处理重构为一个handleErrors()
函数:
function handleErrors(response) {
if (!response.ok) {
throw Error(response.statusText);
}
return response;
}
fetch("http://httpstat.us/500")
.then(handleErrors)
.then(function(response) {
console.log("ok");
}).catch(function(error) {
console.log(error);
});
为了增加乐趣,您可以使用ES6 箭头函数来使回调格式不那么冗长:
function handleErrors(response) {
if (!response.ok) {
throw Error(response.statusText);
}
return response;
}
fetch("http://httpstat.us/500")
.then(handleErrors)
.then(response => console.log("ok") )
.catch(error => console.log(error) );
离别的思念
尽管我仍然不喜欢fetch()
‘ 拒绝失败的 HTTP 状态代码的缺乏,但随着时间fetch()
的推移,我的行为越来越多——主要是因为它让我可以更好地控制我如何处理个别问题。另外,它的可组合性fetch()
使得手动处理错误而不添加一堆冗长的代码变得相当简单。
总的来说,我认为值得花几分钟来玩fetch()
,即使只是看看你的想法。它肯定是比 XMLHttpRequest 更具可读性的替代方案。如果您碰巧正在构建NativeScript应用程序,您可能不知道您现在可以使用而不fetch()需要任何 polyfill 或后备。还有一些关于fetch()
在原生 Android 和 iOS 应用程序中执行 HTTP 请求的东西简直太酷了 :)
还没有评论,来说两句吧...