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

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

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

Headers

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

还有就是查询的某些接口返回的是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相应的结果:

结语

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

参考