传统 Ajax 已死,Fetch 永生
原谅我做一次标题党,Ajax 不会死,传统 Ajax 指的是 XMLHttpRequest(XHR), 最近把阿里一个千万级 PV 的数据产品全部由 jQuery 的 由于 Fetch API 是基于 Promise 设计,有必要先学习一下 Promise,推荐阅读 MDN Promise 教程。旧浏览器不支持 Promise,需要使用 polyfill es6-promise 。 本文不是 Fetch API 科普贴,其实是讲异步处理和 Promise 的。Fetch API 很简单,看文档很快就学会了。推荐 MDN Fetch 教程 和 万能的WHATWG Fetch 规范 Why FetchXMLHttpRequest 是一个设计粗糙的 API,不符合关注分离(Separation of Concerns)的原则,配置和调用方式非常混乱,而且基于事件的异步模型写起来也没有现代的 Promise,generator/yield,async/await 友好。 Fetch 的出现就是为了解决 XHR 的问题,拿例子说明: 使用 XHR 发送一个 json 请求一般是这样: var xhr = new XMLHttpRequest(); xhr.open('GET',url); xhr.responseType = 'json'; xhr.onload = function() { console.log(xhr.response); }; xhr.onerror = function() { console.log("Oops,error"); }; xhr.send(); 使用 Fetch 后,顿时看起来好一点 fetch(url).then(function(response) { return response.json(); }).then(function(data) { console.log(data); }).catch(function(e) { console.log("Oops,error"); }); 使用 ES6 的 箭头函数 后: fetch(url).then(response => response.json()) .then(data => console.log(data)) .catch(e => console.log("Oops,error",e)) 现在看起来好很多了,但这种 Promise 的写法还是有 Callback 的影子,而且 promise 使用 catch 方法来进行错误处理的方式有点奇怪。不用急,下面使用 async/await 来做最终优化:
try { let response = await fetch(url); let data = response.json(); console.log(data); } catch(e) { console.log("Oops,e); } // 注:这段代码如果想运行,外面需要包一个 async function duang~~ 的一声,使用 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 的基本原理是探测是否存在 终于,引用了这一堆 polyfill 后,可以愉快地使用 Fetch 了。但要小心,下面有坑: Fetch 常见坑
竟然没有提到 IE,这实在太不科学了,现在来详细说下 IE IE 使用策略所有版本的 IE 均不支持原生 Fetch,fetch-ie8 会自动使用 XHR 做 polyfill。但在跨域时有个问题需要处理。 IE8,9 的 XHR 不支持 CORS 跨域,虽然提供 标准 Promise 的不足由于 Fetch 是典型的异步场景,所以大部分遇到的问题不是 Fetch 的,其实是 Promise 的。ES6 的 Promise 是基于 Promises/A+ 标准,为了保持简单简洁,只提供极简的几个 API。如果你用过一些牛 X 的异步库,如 jQuery(不要笑) 、Q.js 或者 RSVP.js,可能会感觉 Promise 功能太少了。 没有 DeferredDeferred 可以在创建 Promise 时可以减少一层嵌套,还有就是跨方法使用时很方便。 没有获取状态方法:isRejected,isResolved标准 Promise 没有提供获取当前状态 rejected 或者 resolved 的方法。只允许外部传入成功或失败后的回调。我认为这其实是优点,这是一种声明式的接口,更简单。 缺少其它一些方法:always,progress,finallyalways 可以通过在 then 和 catch 里重复调用方法实现。finally 也类似。progress 这种进度通知的功能还没有用过,暂不知道如何替代。 最后Fetch 替换 XHR 只是时间问题,现在看到国外很多新的库都默认使用了 Fetch。 最后再做一个大胆预测:由于 async/await 这类新异步语法的出现,第三方的 Promise 类库会逐渐被标准 Promise 替代,使用 polyfill 是现在比较明智的做法。
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |