参考:
developers.google.com/web/updates…
现在可能还有一些很旧的程序还在使用XHR,类似下面的写法:
const request = new XMLHttpRequest() request.responseType = 'json' request.open('GET', '/url', true) request.onload = () => { console.log(request.response) } request.onerror = () => { console.log('shits happen!') } request.send(null)
这样子使用XHR进行异步访问、读取资源显得很繁琐,相对比Fetch()允许你创建类似XHR的network访问,但是使用更简单而且干净的API,不需要多次回调并且记住XHR复杂的API。Fetch API底层是通过Promises实现。
XMLHttpRequest
一个相对完整的XMLHttpRequest至少需要监听两个事件(onload、onerror)来实现成功和失败的回调,以及调用open()和send()
function reqListener() { var data = JSON.parse(this.responseText); console.log(data); } function reqError(err) { console.log('Fetch Error :-S', err); } var oReq = new XMLHttpRequest(); oReq.onload = reqListener; oReq.onerror = reqError; oReq.open('get', './api/some.json', true); oReq.send();
Fetch
一个简单的Fetch例子如下:
fetch('./api/some.json') .then( function(response) { if (response.status !== 200) { console.log('Looks like there was a problem. Status Code: ' + response.status); return; } // Examine the text in the response response.json().then(function(data) { console.log(data); }); } ) .catch(function(err) { console.log('Fetch Error :-S', err); });
Fetch的语法更加语义化、比较好理解。在上面的例子里我们先判断response的status码,如果是200我们才将response解析为JSON
fetch()请求返回的response是Stream对象,因此我们调用response.json时由于异步读取流对象所以返回的是一个Promise对象。
Fetch用async优化代码
由于Fetch底层是用Promise实现,我们可以直接用async来优化上面的代码,减少回调,使其更加语义化、容易理解
async function geturl(){ try{ let res = await fetch('./api/some.json') if(res.status == 200){ console.log(await res.text()) } } catch(err){ console.log(err) } }
Response元数据
在上面的例子里,我们了解了Response对象的status状态以及怎么把response对象转换为JSON对象,让我们来看看Response对象的其他元数据:
fetch('users.json').then(function(response) { console.log(response.headers.get('Content-Type')); console.log(response.headers.get('Date')); console.log(response.status); console.log(response.statusText); console.log(response.type); console.log(response.url); });
Response类型
当我们发起一个Fetch请求时,返回的response响应会自带一个response.type属性(basic、cors、opaque)。response.type属性说明了异步资源的来源,同时还有相应的处理方式。
当我们发起一个同源请求时,response.type为basic,而且你可以从response读取全部信息。
如果我们访问一个非同源域名,并且有返回相应的CORs响应头时,那么该请求类型是cors。cors和basic很相似,就除了cors响应里你无法访问 Cache-Control
, Content-Language
, Content-Type
, Expires
, Last-Modified
和 Pragma
当我们对一个不同源的域名发起请求时,如果返回的响应头部没有CORS信息,那么这个response对应的类型就是opaque类型。一个opaque响应是无法读取返回的数据、状态,甚至无法确定这个请求是否成功。
我们可以自定义Fetch请求的模式,要求返回对应类型的响应,有以下几种响应:
- same-origin 只返回同源请求,其他类型会被reject
- cors 接收同源、非同源请求,返回有CORs头部的响应
- cors-with-forced-preflight 在发出请求前会先做一次安全性检查
-
no-cors 用来发起没有CORS头部并且非同源请求,并且会返回opaque响应。但是目前这种类型只能在Service Worker里使用,在window.fetch里不能用
fetch('http://some-site.com/cors-enabled/some.json', {mode: 'cors'}) .then(function(response) { return response.text(); }) .then(function(text) { console.log('Request successful', text); }) .catch(function(error) { log('Request failed', error) });
承诺链
因为Fetch返回的response是基于Promise实现,所以我们可以像链条一样把几个Promise串接起来,如下所示:
function status(response) { if (response.status >= 200 && response.status < 300) { return Promise.resolve(response) } else { return Promise.reject(new Error(response.statusText)) } } function json(response) { return response.json() } fetch('users.json') .then(status) .then(json) .then(function(data) { console.log('Request succeeded with JSON response', data); }).catch(function(error) { console.log('Request failed', error); });
当然了,我们也可以用async进行代码优化
async function geturl(url){ try { let res = await fetch(url) if(res.status >= 200 && res.status < 300){ console.log('Request succeeded with JSON response', await res.json()) } }catch (err){ console.log(err) } } geturl('users.json')
Post请求
当我们使用Fetch发起Post请求时,需要手动设置method参数和body参数,如下:
fetch(url, { method: 'post', headers: { "Content-type": "application/x-www-form-urlencoded; charset=UTF-8" }, body: 'foo=bar&lorem=ipsum' }) .then(json) .then(function (data) { console.log('Request succeeded with JSON response', data); }) .catch(function (error) { console.log('Request failed', error); });
如果没有显式指定method参数,那么默认Get请求
注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。