说明
由于 Fetch API 是基于 Promise 设计,有必要先学习一下 Promise。旧浏览器不支持 Promise,需要使用 polyfill es6-promise 。
如果不支持fetch也没有问题,可以使用第三方的ployfill来实现只会fetch:whatwg-fetch 这个用的人多。
开始
发送一个json请求
XHR方式
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(res) {return res.json()}).then(function(data) {console.log(data);}).catch(function(e) {console.error(e)})
或者:
fetch(url).then(response => response.json()).then(data => console.log(data)).catch(e => console.error(e))
再或者:
async/await 是非常新的 API,属于 ES7
try{let res = await fetch(url)let data = await res.json()console.log(data)}catch(e) {console.error(e)}
使用 await 后,写异步代码就像写同步代码一样爽。await 后面可以跟 Promise 对象,表示等待 Promise resolve() 才会继续向下执行,如果 Promise 被 reject() 或抛出异常则会被外面的 try…catch 捕获。
fetch GET请求初步
fetch(url, {method: 'GET'}).then((res) => {return res.text()}).then((res) => {console.log(res)})
fetch GET请求的参数传递
fetch(url + '?a=1&b=2', { // 在URL中写上传递的参数method: 'GET'}).then((res) => {return res.text()}).then((res) => {console.log(res)})
fetch POST请求初步
fetch(url, {method: 'POST' // 指定是POST请求}).then((res)=>{return res.text()}).then((res)=>{console.log(res)})
fetch POST请求参数的传递
let formData = new FormData()formData.append('foo', 1)formData.append('bar', 2)fetch(url, {method: 'POST',body: formData,// 这里是请求对象}).then((res) => {return res.text()}).then((res) => {console.log(res)})
fetch 设置请求的头信息
在POST提交的过程中,一般是表单提交,可是,经过查询,发现默认的提交方式是:Content-Type:text/plain;charset=UTF-8,这个显然是不合理的。
fetch(url, {method: 'POST',headers: new Headers({'Content-Type': 'application/x-www-form-urlencoded' // 指定提交方式为表单提交}),body: new URLSearchParams([["foo", 1],["bar", 2]]).toString()}).then((res)=>{return res.text()}).then((res)=>{console.log(res)})
fetch 通过接口得到JSON数据
上面所有的例子中都是返回一个文本
fetch(url, { // 在URL中写上传递的参数method: 'GET',headers: new Headers({'Accept': 'application/json' // 通过头指定,获取的数据类型是JSON})}).then((res) => {return res.json() // 返回一个Promise,可以解析成JSON}).then((res) => {console.log(res) // 获取JSON数据})
fetch 强制带Cookie
默认情况下, fetch 不会从服务端发送或接收任何 cookies, 如果站点依赖于维护一个用户会话,则导致未经认证的请求(要发送 cookies,必须发送凭据头).
fetch(url, {
method: ‘GET’,
credentials: ‘include’ // 强制加入凭据头
})
fetch 简单封装一下
/*** 将对象转成 a=1&b=2的形式* @param obj 对象*/function obj2String(obj, arr = [], idx = 0) {for (let item in obj) {arr[idx++] = [item, obj[item]]}return new URLSearchParams(arr).toString()}/*** 真正的请求* @param url 请求地址* @param options 请求参数* @param method 请求方式*/function commonFetcdh(url, options, method = 'GET') {const searchStr = obj2String(options)let initObj = {}if (method === 'GET') { // 如果是GET请求,拼接urlurl += '?' + searchStrinitObj = {method: method,credentials: 'include'}} else {initObj = {method: method,credentials: 'include',headers: new Headers({'Accept': 'application/json','Content-Type': 'application/x-www-form-urlencoded'}),body: searchStr}}fetch(url, initObj).then((res) => {return res.json()}).then((res) => {return res})}/*** GET请求* @param url 请求地址* @param options 请求参数*/function GET(url, options) {return commonFetcdh(url, options, 'GET')}/*** POST请求* @param url 请求地址* @param options 请求参数*/function POST(url, options) {return commonFetcdh(url, options, 'POST')}
GET('https://www.baidu.com/search/error.html', {a:1,b:2})POST('https://www.baidu.com/search/error.html', {a:1,b:2})
支持

原生支持率并不高,幸运的是,引入下面这些 polyfill 后可以完美支持 IE8+ :
- 由于 IE8 是 ES3,需要引入 ES5 的 polyfill: es5-shim,es5-sham
- 引入 Promise 的 polyfill: es6-promise
- 引入 fetch 探测库:fetch-detector
- 引入 fetch 的 polyfill: fetch-ie8
- 可选:如果你还使用了 jsonp,引入 fetch-jsonp
- 可选:开启 Babel 的 runtime 模式 或者 使用regenerator,现在就使用 async/await
常见问题
- Fetch 请求默认是不带 cookie 的,需要设置
fetch(url, {credentials: 'include'})。 - 服务器返回 400,500 错误码时并不会 reject,只有网络错误这些导致请求不能完成时,fetch 才会被 reject。
- 所有版本的 IE 均不支持原生 Fetch,fetch-ie8 会自动使用 XHR 做 polyfill。但在跨域时有个问题需要处理。IE8, 9 的 XHR 不支持 CORS 跨域。
- Response返回一个被解析后的promise对象和数据,有这些解析方式:arrayBuffer()、blob()、、json()、text()、formData()
参考
总结
- 语法简洁,更加语义化
- 基于标准 Promise 实现,支持 async/await
- 同构方便,使用isomorphic-fetch
注:同构(isomorphic/universal)就是使前后端运行同一套代码的意思,后端一般是指 NodeJS 环境。
