转载

Fetch API: 异步请求新解决方案

浏览器通过XMLHttpRequest(XHR)来实现异步请求,但是这种方式存在如下问题:

  • 职责不分离: 输入、输出、结果处理均通过XHR对象来完成
  • 事件机制: 结果的处理通过事件模型来完成,会存在回调嵌套问题(callback hell),这与流行的Promise不搭配

基于以上原因,出现了 fetch api ,也经常跟service worker一起搭配使用。fetch api下存在Headers、Request、Response三个类,直接与HTTP的相关定义对应起来,异步操作变得更加灵活、强大。

Headers

通过Headers,可以方便地对request、response的Headers信息进行增、删、改、查的操作:

  • 增: Headers.prototype.append
  • 删: Headers.prototype.delete
  • 该: Headers.prototype.set
  • 查: Headers.prototype.get、Headers.prototype.getAll、Headers.prototype.entries、Headers.prototype.keys、Headers.prototype.has

还有就是查询的某些接口返回的是iterator,这样就可以使用for…of进行遍历:

const header = new Headers; header.append('content-type', 'application'); header.append('connection', 'keep-alive');  for (let item of header.entries()) {   console.log(item) } // ["content-type", "application"] // ["connection", "keep-alive"]  // 上述代码可以直接写成 for (let item of header) {   console.log(item) } 

其中因为安全因素, Headers有些属性是不可写的,header对象中存在一个不对外的属性 guard ,规定了不同情况( none / request / request-no-cors / response / immutable )下Headers的行为。

Body

无论Request还是Response,里面均存在 body 属性,该属性存储请求的内容,由于javascript里面数据类型的复杂性: ArrayBufferBlobstringURLSearchParamFormData ,所以fetch提供了mixin类 Body ,用于处理不同类型的数据。

Body除了具有相关数据类型的处理方法外,还有一个字段 bodyUsed ,用于标示该 body 是否已经被读取。因为 body 是stream,只能被读取一次。

那么如何要多次读取 body 里面的内容,就需要首先进行 clone

Request

Request定义了HTTP请求获取资源的request格式,接受两个参数: urloptions ,实际中往往不需要手动new一个request对象,通过其他操作会返回一个request对象:

const req = new Request('http://example.com/api/data', {    method: 'POST',    headers: {      'content-type': 'application/json',    },    body: 'name=test&age=12',    mode: 'cors',    credentials: 'include', });  console.log('request body is readed ? : ',req.bodyUsed); req.json().then((json) => { console.log(json);   console.log('request body is readed ? : ',req.bodyUsed); }).catch((err) => {   console.log(err) });  // request body is readed ? :  false // demo:13 Object {name: "test", count: 123} // request body is readed ? :  true 

相对于XHR方式,Request对象可以很方便、明确地显示是否允许跨域(mode)、是否需要携带cookie(credentials)等。

Response

Response对应http的相应,里面包含了服务相应的相关信息,除了在service worker中,是不需要显示创建。

fetch('/api/data').then((res) => {   console.log('res headers: ', res);   return res.json(); }).then((json) => {   console.log('json2 is: ', json); }).catch((err) => {   console.log('the error is: ', err); }) 

Response里面存在如下属性来描述HTTP相应的结果:

  • status/statusText/ok: 藐视该请求的状态,其中当 status=2** 时, ok === true
  • type: 其中肯呢过为 basiccorserroropaque ,指明该HTTP请求是否跨域、错误等信息
  • body: 存储响应的内容

结语

在github上已经出现了fetch的 polyfill ,并且非常流行,厌倦XHR写法的同学可以尝试该方法来解决异步请求问题。

参考

  • https://hacks.mozilla.org/2015/03/this-api-is-so-fetching/
  • https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
  • https://github.com/github/fetch
原文  http://zhenhua-lee.github.io/http/fetch.html
正文到此结束
Loading...