-
Notifications
You must be signed in to change notification settings - Fork 257
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
传统 Ajax 已死,Fetch 永生 #2
Comments
不错的文章,赞 |
谢谢科普!赞赞赞b( ̄▽ ̄)d |
火钳刘明 |
不错的文章,赞 |
Fetch 永生 |
学到了 |
学习了 |
确实有点标题 |
写的不错,还好我的前端组件跟请求都是分离的 |
围观 |
科普的不错。新的项目正在使用~ |
科普下。说不定就用的上 |
顶下 |
滚粗,标题党。 ajax的promise 写法而已,没有本质差别。 IE11都还要 polyfill的支持, 产品环境用起来也太麻烦 |
另一种选择,值得一看。 |
polyfill 用的太多了,生产环境用起来压力太大 |
@kisnows 个数多而已,代码没多少,我们千万级 PV 产品一直运行稳定 |
get it |
btw, how do i log an issue for an issue? 😄 |
@ralphite wow, nice catch 🌟 |
但是看起來並沒有比較簡潔好寫啊?有辦法比較其中的效能嗎 |
Copy that http://www.rehack.cn/ |
@fifiteen82726 搭配 async/await 應該非常簡潔吧? |
在IE里面 我导入了 <script src="./es5-shim.min.js"></script>
然后在点击按钮 变成下载文件了 (文件里面是后端返回的JSON) |
@gdzgshum fetch-ie8 和 fetch-detector 要以 CommonJS 方式引用,要使用 Webpack 来打包。如果想用 ES6 语法,就用 Babel 编译一下 |
mark!!! |
@liyatang 测试了一下 Chrome 会把设置的 |
@camsong 看官方的解释说正常,标准如此https://fetch.spec.whatwg.org/#terminology-headers 附上issue 链接 |
@liyatang 赞高效率,原来这并不是 bug,我也学习了,顺便再补充一下: 根据 HTTP 规范(RFC 7230,RFC 2616),HTTP header 的 name 是不区分大小写的。 |
fetch在google和Firefox发请求时,添加请求头后,Firefox无法正常返回数据。 |
自己已经解决,原因是因为服务端设置有问题 |
onlooker |
@liangklfangl |
|
文章大部分提到的概念内容都可以从其他渠道去仔细研究和推敲,谢谢博主 |
promise, 箭头函数, async/await和xhr不冲突吧, 所以fetch究竟比xhr好在哪里(⊙_⊙)? |
🐎 |
请教作者:
|
response.json()这个方法是异步的吗,为什么要加await |
json 方法返回的是一个 Promise |
谢谢大佬 |
“服务器返回 400,500 错误码时并不会 reject,只有网络错误这些导致请求不能完成时,fetch 才会被 reject。” 这个是啥意思? 能具体说一下吗,意思是说 业务层的状态码不会导致 reject 只有http code 是非200 才会导致reject吗? 还是说其 他的情况? 网络错误导致请求不能完成,具体是哪种情况啊 |
试用了下,fetch性能上貌似比xhr还差些 |
这是来自QQ邮箱的假期自动回复邮件。您好,我最近正在休假中,无法亲自回复您的邮件。我将在假期结束后,尽快给您回复。
|
原谅我做一次标题党,Ajax 不会死,传统 Ajax 指的是 XMLHttpRequest(XHR),
未来现在已被 Fetch 替代。最近把阿里一个千万级 PV 的数据产品全部由 jQuery 的
$.ajax
迁移到Fetch
,上线一个多月以来运行非常稳定。结果证明,对于 IE8+ 以上浏览器,在生产环境使用 Fetch 是可行的。由于 Fetch API 是基于 Promise 设计,有必要先学习一下 Promise,推荐阅读 MDN Promise 教程。旧浏览器不支持 Promise,需要使用 polyfill es6-promise 。
本文不是 Fetch API 科普贴,其实是讲异步处理和 Promise 的。Fetch API 很简单,看文档很快就学会了。推荐 MDN Fetch 教程 和 万能的WHATWG Fetch 规范
Why Fetch
XMLHttpRequest 是一个设计粗糙的 API,不符合关注分离(Separation of Concerns)的原则,配置和调用方式非常混乱,而且基于事件的异步模型写起来也没有现代的 Promise,generator/yield,async/await 友好。
Fetch 的出现就是为了解决 XHR 的问题,拿例子说明:
使用 XHR 发送一个 json 请求一般是这样:
使用 Fetch 后,顿时看起来好一点
使用 ES6 的 箭头函数 后:
现在看起来好很多了,但这种 Promise 的写法还是有 Callback 的影子,而且 promise 使用 catch 方法来进行错误处理的方式有点奇怪。不用急,下面使用 async/await 来做最终优化:
duang~~ 的一声,使用
await
后,写异步代码就像写同步代码一样爽。await
后面可以跟 Promise 对象,表示等待 Promiseresolve()
才会继续向下执行,如果 Promise 被reject()
或抛出异常则会被外面的try...catch
捕获。Promise,generator/yield,await/async 都是现在和未来 JS 解决异步的标准做法,可以完美搭配使用。这也是使用标准 Promise 一大好处。最近也把项目中使用第三方 Promise 库的代码全部转成标准 Promise,为以后全面使用 async/await 做准备。
另外,Fetch 也很适合做现在流行的同构应用,有人基于 Fetch 的语法,在 Node 端基于 http 库实现了 node-fetch,又有人封装了用于同构应用的 isomorphic-fetch。
总结一下,Fetch 优点主要有:
Fetch 启用方法
下面是重点↓↓↓
先看一下 Fetch 原生支持率:
原生支持率并不高,幸运的是,引入下面这些 polyfill 后可以完美支持 IE8+ :
Fetch polyfill 的基本原理是探测是否存在
window.fetch
方法,如果没有则用 XHR 实现。这也是 github/fetch 的做法,但是有些浏览器(Chrome 45)原生支持 Fetch,但响应中有中文时会乱码,老外又不太关心这种问题,所以我自己才封装了fetch-detector
和fetch-ie8
只在浏览器稳定支持 Fetch 情况下才使用原生 Fetch。这些库现在 每天有几千万个请求都在使用,绝对靠谱 !终于,引用了这一堆 polyfill 后,可以愉快地使用 Fetch 了。但要小心,下面有坑:
Fetch 常见坑
fetch(url, {credentials: 'include'})
竟然没有提到 IE,这实在太不科学了,现在来详细说下 IE
IE 使用策略
所有版本的 IE 均不支持原生 Fetch,fetch-ie8 会自动使用 XHR 做 polyfill。但在跨域时有个问题需要处理。
IE8, 9 的 XHR 不支持 CORS 跨域,虽然提供
XDomainRequest
,但这个东西就是玩具,不支持传 Cookie!如果接口需要权限验证,还是乖乖地使用 jsonp 吧,推荐使用 fetch-jsonp。如果有问题直接提 issue,我会第一时间解决。Fetch 和标准 Promise 的不足
由于 Fetch 是典型的异步场景,所以大部分遇到的问题不是 Fetch 的,其实是 Promise 的。ES6 的 Promise 是基于 Promises/A+ 标准,为了保持 简单简洁 ,只提供极简的几个 API。如果你用过一些牛 X 的异步库,如 jQuery(不要笑) 、Q.js 或者 RSVP.js,可能会感觉 Promise 功能太少了。
没有 Deferred
Deferred 可以在创建 Promise 时可以减少一层嵌套,还有就是跨方法使用时很方便。
ECMAScript 11 年就有过 Deferred 提案,但后来没被接受。其实用 Promise 不到十行代码就能实现 Deferred:es6-deferred。现在有了 async/await,generator/yield 后,deferred 就没有使用价值了。
没有获取状态方法:isRejected,isResolved
标准 Promise 没有提供获取当前状态 rejected 或者 resolved 的方法。只允许外部传入成功或失败后的回调。我认为这其实是优点,这是一种声明式的接口,更简单。
缺少其它一些方法:always,progress,finally
always 可以通过在 then 和 catch 里重复调用方法实现。finally 也类似。progress 这种进度通知的功能还没有用过,暂不知道如何替代。
不能中断,没有 abort、terminate、onTimeout 或 cancel 方法
Fetch 和 Promise 一样,一旦发起,不能中断,也不会超时,只能等待被 resolve 或 reject。幸运的是,whatwg 目前正在尝试解决这个问题 whatwg/fetch#27
资料
最后
Fetch 替换 XHR 只是时间问题,现在看到国外很多新的库都默认使用了 Fetch。
最后再做一个大胆预测:由于 async/await 这类新异步语法的出现,第三方的 Promise 类库会逐渐被标准 Promise 替代,使用 polyfill 是现在比较明智的做法。
The text was updated successfully, but these errors were encountered: