前端⼯程师使⽤fetch常见的四种错误(翻译)
查看
是浏览器中发送http请求最流⾏⽅式。它不仅仅是⼀个⽐更好、更符合⼈体⼯程学的API,它还带来了许多令⼈兴奋的新功能,⽐如响应流、对凭证和CORS请求的更多控制,以及与ServiceWorkers和缓存API的集成
我⾃⼰也在研究并使⽤它,同时也见证了的成长(原⽂:⼴泛使⽤), 发现即使有经验的开发者也会犯⼀些⽐较常见的错误。我认为这在很⼤程度上与的API在表⾯上看起来它的⾏为模式都很像jQuery 、angularJS的、 等。它们之间有⼀些重要的区别,⽽这些区别⼤多源于作为底层⽹络请求的原型设计
1.认为⼀旦发⽣http错误,promise 就会被 reject
Fetch是基于promise的,因此⽐较容易想到,如果服务器返回,像404或是500,Promise就会被拒绝,就像原始的XMLHttpRequest⼀样;但fetch并不是这样的——它仅仅在发⽣“network error(⽹络错误)”才会被拒绝(这是⼀个令⼈困惑的术语,但规范是这么说的)。如果可以服务器获得http错误状态,则表明服务器正常⼯作且在处理请求,⽽“network error(⽹络错误)”表⽰根本⽆法到达服务器(例如连接拒绝或名称未解析)或请求配置有错误(错误的请求地址)。
例如, ftp 协议 并不⽀持fetch,所以它会返回⼀个被rejected 的 promise :
fetch('ftp://example')  .catch(err => ('Caught error: ', err))复制代码
但是请求⼀个返回404错误的URL并有没有发⽣错误(即类似404这类错误fetch返回的并不是rejected)
fetch('picode/404')
.then(res => console.log('response: ', res))  .)复制代码
我想对⼤部分开发者来说,http返回的错误对web应⽤程序处理⼀个rejected的promise是⾮常有⽤的。为此(fetch对http错误的处理⽅式),我们仅仅需要对验证 ok  属性的值 ,如果  ok
的值为false ,则 reject
fetch('picode/404')
.then(res => {
if(res.ok) {
return res;
} else {
throw Error(`Request rejected with status ${res.status}`);
}})
.)复制代码
2.忘记包含credentials
与XHR不同,fetch在默认情况下不包括请求中的任何cookie。因此,如果针对您的API的请求需要基于cookie的授权(⼤多数web应⽤程序都需要),那么必须有这个选项,否则您的调⽤可能会返回401未授权。
这⾮常简单:
fetch('/url', { credentials: 'include' })复制代码
注意,如果您正在使⽤fetch polyfill,那么(不幸的是)您可能会偶尔地忘记这⼀点,⼀切看起来就好像
你已经正在使⽤credentials:
'include'⼀样,这是因为它只是在底层使⽤XHR,⽽XHR⾃动具有这种⾏为。
3.上传JSON时忘记设置`Content-Type` to `application/json`
$http, axios和其它http⼯具在默认情况下会为您设置此头,因此很容易忘记。
fetch('cameronnokes/slack-ron-swanson-quote-bot/ron', {
method: 'POST',
body: JSON.stringify({text: 'bacon'}),
headers: {'Content-Type': 'application/json'}})
.then(res => res.json())
.then(console.log)复制代码
如果不包含该头,服务器可能会返回⼀个400个Bad Request ,因为endpoint不⽀持纯⽂本内容类型,
或者⽆法处理这种⽂本的body,这取决于API的实现。但⽆论如何,您的API可能会返回HTTP错误状态。
4.使⽤字符串⼿动拼接⼀个复杂的查询参数
我经常看到类似这样的代码:
fetch('/endpoint?foo=${n > 1 ? 123 : 456}&bar=abc&query=${encodeURIComponent(someString || '')}复制代码
angular和angularjs
这并不完全是糟糕的,但我认为如果我们让新的URLSearchParams类和少量lodash为我们做更多的⼯作,它会更容易阅读,更少出错。
URLSearchParams类⾮常棒,可以正确地处理编码、将对象连接到字符串等等。我认为这样更容易阅读和维护。
总结:
Fetch很棒,但是要负责任地去享受
======================= 以下为译者添加=========================
伴随的问世及发展,⽬前在⽣产环境使⽤fetch的企业越来越多。开源社区上有关fetch polyfilll已经多款供选,⼜因其基于Promise,以下可以完美的解决其兼容性问题(特别是IE),仅参考:
由于 IE8 是 ES3,需要引⼊ ES5 的 polyfill: es5-shim, es5-sham
引⼊ Promise 的 polyfill: es6-promise
引⼊ fetch 探测库:fetch-detector
引⼊ fetch 的 polyfill: fetch-ie8
可选:如果你还使⽤了 jsonp,引⼊ fetch-jsonp
可选:开启 Babel 的 runtime 模式,现在就使⽤ async/await
fetch 的好处⽆需多语,但fetch也存在⼀些问题,例如不⽀持timeout,不⽀持 progress,特别是fetch在跨域问题上与传统跨域的处理⽅式的区别,社区中都对应的解决⽅案,此⽂不⼀⼀列举。正如原谅作者所⾔:负责任地去享受

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。