一、什么是fetch?
全局的 fetch() 方法用于发起获取资源的请求。它返回一个 promise,这个 promise 会在请求响应后被 resolve,并传回 Response 对象。
Window 和 WorkerGlobalScope 都实现了 WorkerOrGlobalScope。 ——这意味着基本在任何场景下只要你想获取资源,都可以使用 位于 WorkerOrGlobalScope 中的 fetch() 方法。
当遇到网络错误时,fetch() 返回的 promise 会被 reject,并传回 TypeError,虽然这也可能因为权限或其它问题导致。成功的 fetch() 检查不仅要包括 promise 被 resolve,还要包括 Response.ok 属性为 true。HTTP 404 状态并不被认为是网络错误。
fetch() 方法由 Content Security Policy (en-US) 的 connect-src指令控制,而不是它请求的资源。
二、如何使用fetch?
1、fetch语法,包含input和options两个参数:
Promise<Response> fetch(input, options]);
2、fetch参数:
fetch方法可以接收两个参数 input 和 options。
- input 参数可以是字符串,包含要获取资源的 URL。也可以是一个 Request 对象。
- options 是一个可选参数。一个配置项对象,包括所有对请求的设置。
options可选配置有:
method: 请求使用的方法,如GET、POST。headers: 请求的头信息,形式为Headers的对象或包含ByteString值的对象字面量。body: 请求的 body 信息:可能是一个Blob、BufferSource、FormData、URLSearchParams或者USVString对象。注意 GET 或 HEAD 方法的请求不能包含 body 信息。mode: 请求的模式,如cors、no-cors或者same-origin。credentials: 请求的 credentials,如omit、same-origin或者include。为了在当前域名内自动发送 cookie,必须提供这个选项,从 Chrome 50 开始,这个属性也可以接受FederatedCredential(en-US) 实例或是一个PasswordCredential(en-US) 实例。cache: 请求的 cache 模式:default、no-store、reload、no-cache、force-cache或者only-if-cached。redirect: 可用的 redirect 模式:follow(自动重定向),error(如果产生重定向将自动终止并且抛出一个错误),或者manual(手动处理重定向)。在 Chrome 中默认使用follow(Chrome 47 之前的默认值是manual)。referrer: 一个USVString可以是no-referrer、client或一个 URL。默认是client。referrerPolicy: 指定了 HTTP 头部 referer 字段的值。可能为以下值之一:no-referrer、no-referrer-when-downgrade、origin、origin-when-cross-origin、unsafe-url。integrity: 包括请求的 subresource integrity 值(例如:sha256-BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE=)。
三、常用的fetch请求
1、返回HTML
fetch('/users.html')
.then(function(response) {
return response.text()
})
.then(function(body) {
document.body.innerHTML = body
})
.catch((err) => {})
2、返回JSON
fetch('/users.json')
.then(function(response) {
return response.json()
})
.then(function(json) {
console.log('parsed json', json)
})
.catch(function(ex) {
console.log('parsing failed', ex)
})
3、元数据
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)
})
4、表单请求
var form = document.querySelector('form')
fetch('/users', {
method: 'POST',
body: new FormData(form)
})
5、JSON请求
fetch('/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Hubot',
login: 'hubot',
})
})
6、文件上传
var input = document.querySelector('input[type="file"]')
var data = new FormData()
data.append('file', input.files[0])
data.append('user', 'hubot')
fetch('/avatars', {
method: 'POST',
body: data
})
四、取消请求
fetch自身并没有提供中止请求的方法,如果需要取消请求需借助AbortController和AbortSignal,目前有些浏览器已经实现了AbortController和AbortSignal,此时,我们可以通过AbortController中止fetch请求。
如上面截图,如果fetch设置了signal,然后可以执行 controller.abort() 方法终止请求,假设浏览器不支持AbortController和AbortSignal,但我们又想终止请求,我们该怎么办?此时,我们可以借助yet-another-abortcontroller-polyfill来实现,具体参考如下:
import 'yet-another-abortcontroller-polyfill'
import {fetch} from 'whatwg-fetch'
// use native browser implementation if it supports aborting
const abortableFetch = ('signal' in new Request('')) ? window.fetch : fetch
const controller = new AbortController()
abortableFetch('/avatars', {
signal: controller.signal
}).catch(function(ex) {
if (ex.name === 'AbortError') {
console.log('request aborted')
}
})
// some time later...
controller.abort()
五、拓展:
在整理fetch的过程中,发现了几个之前没注意到的构造函数,可以用作接口的请求和响应:
1、 Headers
其中Headers可以是多个键值对,使用如下:
const content = 'Hello World';
const myHeaders = new Headers();
myHeaders.append('Content-Type', 'text/plain');
myHeaders.append('Content-Length', content.length.toString());
myHeaders.append('X-Custom-Header', 'ProcessThisImmediately');
或者是一个对象:
const myHeaders = new Headers({
'Content-Type': 'text/plain',
'Content-Length': content.length.toString(),
'X-Custom-Header': 'ProcessThisImmediately'
});
guard
由于 Headers 可以在 request 中被发送或者在 response 中被接收,并且规定了哪些参数是可写的,Headers 对象有一个特殊的 guard 属性。这个属性没有暴露给 Web,但是它影响到哪些内容可以在 Headers 对象中被操作。 可能的值如下:
none:默认的。request:从 request 中获得的 headers(Request.headers)只读。request-no-cors:从不同域(Request.modeno-cors)的 request 中获得的 headers 只读。response:从 response 中获得的 headers(Response.headers)只读。immutable:在 ServiceWorkers 中最常用的,所有的 headers 都只读。
2、 Request
综合headers和requests的使用如下:
const myHeaders = new Headers();
const myRequest = new Request('flowers.jpg', {
method: 'GET',
headers: myHeaders,
mode: 'cors',
cache: 'default',
});
fetch(myRequest)
.then(response => response.blob())
.then(myBlob => {
myImage.src = URL.createObjectURL(myBlob);
});
其中,requests的语法如下,包含input和options两个参数:
var myRequest = new Request(input, options);
input:
其值可以是下面两者之一:
-
一个直接包含你希望 fetch 的资源的 URL 的
USVString。 -
一个
Request对象。请注意以下行为更新,以在保留安全性的同时使构造函数不太可能引发异常:- 如果此对象存在于构造函数调用的另一个起源上,则将除去[`Request.referrer` (en-US)](https://developer.mozilla.org/en-US/docs/Web/API/Request/referrer "Currently only available in English (US)")。 - 如果此对象的导航为 [`Request.mode`](https://developer.mozilla.org/zh-CN/docs/Web/API/Request/mode),则`mode`将转换为`same-origin`
options:
一个可选对象,包含希望被包括到请求中的各种自定义选项。可用的选项如下:
method: 请求的方法,例如:GET,POST。headers: 任何你想加到请求中的头,其被放在Headers对象或内部值为ByteString的对象字面量中。body: 任何你想加到请求中的 body,可以是Blob,BufferSource,FormData,URLSearchParams,USVString,或ReadableStream对象。注意GET和HEAD请求没有 body。mode: 请求的模式,比如cors,no-cors,same-origin, 或navigate。默认值为cors。credentials: 想要在请求中使用的 credentials::omit,same-origin, 或include。默认值应该为omit。但在 Chrome 中,Chrome 47 之前的版本默认值为same-origin,自 Chrome 47 起,默认值为include。cache: 请求中想要使用的 cache moderedirect: 对重定向处理的模式:follow,error, ormanual。在 Chrome 中,Chrome 47 之前的版本默认值为manual,自 Chrome 47 起,默认值为follow。referrer: 一个指定了no-referrer,client, 或一个 URL 的USVString。默认值是about:client。integrity: 包括请求的 subresource integrity 值 (e.g.,sha256-BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE=).
3、 Response
response的使用大致如下:
const myBody = new Blob();
addEventListener('fetch', event => {
// ServiceWorker intercepting a fetch
event.respondWith(
new Response(myBody, {
headers: { 'Content-Type': 'text/plain' }
})
);
});
相关属性or方法可参考:Response
六、fetch和AbortController以及AbortSignal的兼容性如下:
七、总结:
本篇主要介绍了下:
1、fetch API的常规请求以及取消请求功能
2、可用于请求和响应的Headers, Request和Response构造函数
希望对大家有所帮助或启示,若有错误之处还请大家帮忙指出,感谢~