fetch初识
此功能某些浏览器尚在开发中,请参考浏览器兼容性表格以得到在不同浏览器中适合使用的前缀。由于该功能对应的标准文档可能被重新修订,所以在未来版本的浏览器中该功能的语法和行为可能随之改变。
Note: 如果不需要支持落后的IE系列浏览器,就可以放心大胆的使用吧!
ps: 当然也可以使用第三方的polyfill 库!https://github.com/github/fetch
fetch提供了对于xhr的这种请求中的常见的【请求 Request】、【响应 Response】两个对象的定义,就像node发起一个请求或者响应一个请求一样,创建了request、response两个实例对象,供使用者获取整个请求过程中的请求和响应信息。
它还提供了一种定义,将 CORS 和 HTTP 原生的头信息结合起来,取代了原来那种分离的定义。
fetch() 必须接受一个参数——资源的路径。无论请求成功与否,它都返回一个 promise 对象,resolve 对应请求的 Response。你也可以传一个可选的第二个参数—— init(参考 Request)。
一旦 Response 被返回,就有一些方法可以使用了,比如定义内容或者处理方法(参考 Body)。
你也可以通过 Request() 和 Response() 的构造函数直接创建请求和响应,但是我们不建议这么做。他们应该被用于创建其他 API 的结果(比如,service workers 中的 FetchEvent.respondWith)。
fetch由来
参考:https://developer.mozilla.org…
https://developer.mozilla.org…
https://developer.mozilla.org…
在这里可能需要先说下fetch方法的定义,其最原始的定义是在一个接口叫做GlobalFetch,该接口包含了GlobalFetch.fetch() 方法,Window 和WorkerGlobalScope都实现了GlobalFetch 接口,后来浏览器都把这个接口作了修改,形成了新的mixin,也就是WorkerOrGlobalScope,继而演变为:WindowOrWorkerGlobalScope,WindowOrWorkerGlobalScope混入【mixin】 了对 Window 和WorkerGlobalScope 接口的公共特性的描述【包括常见的setInterval、setTimeout等】。显然除了下文即将列出的之外,这些接口中的每一个,都可以增加更多的特性。
GlobalFetch =》 WorkerOrGlobalScope =》WindowOrWorkerGlobalScope
Note: WindowOrWorkerGlobalScope 是一个 mixin 而并非 interface。不能创建一个类型为 WindowOrWorkerGlobalScope 的对象。
由于 Window 和WorkerGlobalScope都实现了上述mixin,故而可以放心的在全局域下使用fetch,
fetch概念
Fetch 是一个现代的概念, 等同于 XMLHttpRequest。它提供了许多与XMLHttpRequest相同的功能,但被设计成更具可扩展性和高效性。
Fetch 的核心在于对 HTTP 接口的抽象,包括 Request,Response,Headers,Body,以及用于初始化异步请求的 global fetch。得益于 JavaScript 实现的这些抽象好的 HTTP 模块,其他接口能够很方便的使用这些功能。
Service Workers 是一个利用了 Fetch 实现的接口的例子。
除此之外,Fetch 还利用到了请求的异步特性——它是基于 Promise 的。
fettch使用
参考:https://developer.mozilla.org…
https://developer.mozilla.org…
这里先给出一个很简单的例子,以上代码中,我们通过网络获取了一个图片,然后将它插入到一个 <img> 标签中。这个最简单的用法中,fetch() 接受了一个参数——请求的地址——然后返回一个包含 response(一个 Response 对象)的 promise 对象。:
var myImage = document.querySelector('img');
fetch('flowers.jpg')
.then(function(response) {
return response.blob();
})
.then(function(myBlob) {
var objectURL = URL.createObjectURL(myBlob);
myImage.src = objectURL;
});
这个例子很简单,不过还是需要先判断下是否支持fetch:
if(self.fetch) {
// run my fetch request here
} else {
// do something with XMLHttpRequest?
}
上面简单的例子已经包含了response对象、blob方法、then方法;后面一一简述;上面的例子中,fetch函数只是使用了一个参数,也就是url,即获取数据的后段地址,其实还有第二个参数 init对象;
var myHeaders = new Headers();
var myInit = { method: 'GET',
headers: myHeaders,
mode: 'cors',
cache: 'default' };
fetch('flowers.jpg',myInit)
.then(function(response) {
return response.blob();
})
.then(function(myBlob) {
var objectURL = URL.createObjectURL(myBlob);
myImage.src = objectURL;
});
经过进一步的完善,fetch使用变成了这个样子。实际上fetch的定义是这样的:
Promise<Response> fetch(input[, init]);
//another to write the args of fetch 另一种书写方式
var myRequest = new Request(input, init);
Promise<Response> fetch(myRequest);
参数
参数的具体介绍:
参数
input
定义要获取的资源。这可能是:
一个 USVString 字符串,包含要获取资源的 URL。一些浏览器会接受 blob: 和 data: 作为 schemes.
一个 Request 对象。
init 可选
一个配置项对象,包括所有对请求的设置。可选的参数有:
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 实例或是一个 PasswordCredential 实例。
cache: 请求的 cache 模式: default 、 no-store 、 reload 、 no-cache 、 force-cache 或者 only-if-cached 。
redirect: 可用的 redirect 模式: follow (自动重定向), error (如果产生重定向将自动终止并且抛出一个错误), 或者 manual (手动处理重定向). 在Chrome中,Chrome 47之前的默认值是 follow,从 Chrome 47开始是 manual。
referrer: 一个 USVString 可以是 no-referrer、client或一个 URL。默认是 client。
referrerPolicy: Specifies the value of the referer HTTP header. May be one of no-referrer、 no-referrer-when-downgrade、 origin、 origin-when-cross-origin、 unsafe-url 。
integrity: 包括请求的 subresource integrity 值 ( 例如: sha256-BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE=)。
返回值
一个 Promise,resolve 时回传 Response 对象。
Exceptions
Type Description
TypeError Since Firefox 43, fetch() will throw a TypeError if the URL has credentials, such as http://user:password@example.com.
以上可以看到的就是所有的参数,同样也是有两种形式的书写:
myHeaders = new Headers({
"Content-Type": "text/plain",
"Content-Length": content.length.toString(),
"X-Custom-Header": "ProcessThisImmediately",
});
//它的内容可以被获取:
console.log(myHeaders.has("Content-Type")); // true
console.log(myHeaders.has("Set-Cookie")); // false
myHeaders.set("Content-Type", "text/html");
myHeaders.append("X-Custom-Header", "AnotherValue"); //http 头部信息
var myInit = { method: 'GET',
headers: myHeaders,
mode: 'cors',
cache: 'default' };
fetch('flowers.jpg',myInit)
.then(function(response) {......
//或者使用这个来构建fetch参数,所需的参数和fetch所需的参数一样
var anotherRequest = new Request(input,myInit);
其中的头部有些需要注意,详情查看:https://developer.mozilla.org… 可以直接使用Headers构建新的请求头,headers是由键值对构成,不过有的请求头只允许用户代理做修改,详情参见:https://developer.mozilla.org…
同时Guard也是Headers中的重要部分,由于 Headers 可以在 request 请求中被发送或者在 response 请求中被接收,并且规定了哪些参数是可写的,Headers 对象有一个特殊的 guard 属性。这个属性没有暴露给 Web,但是它影响到哪些内容可以在 Headers 对象中被操作。
可能的值如下:
none:默认的
request:从 request 中获得的 headers(Request.headers)只读【后端获取http请求对象】
request-no-cors:从不同域(Request.mode no-cors)的 request 中获得的 headers 只读
response:从 response 中获得的 headers(Response.headers)只读
immutable:在 ServiceWorkers 中最常用的,所有的 headers 都只读
下面分别介绍request、body、response
request请求
了解了以上部分后,就知道可以构建request来发起http请求,
myHeaders = new Headers({
"Content-Type": "text/plain",
"Content-Length": content.length.toString(),
"X-Custom-Header": "ProcessThisImmediately",
});
//它的内容可以被获取:
console.log(myHeaders.has("Content-Type")); // true
console.log(myHeaders.has("Set-Cookie")); // false
myHeaders.set("Content-Type", "text/html");
myHeaders.append("X-Custom-Header", "AnotherValue"); //http 头部信息
//属性
Request.method 只读
请求使用的方法 (GET, POST, 等.)
Request.url 只读
请求使用的 URL。
Request.headers 只读
请求所关联的 Headers 对象。
Request.context 只读
请求的上下文 例如:(例如:audio, image, iframe, 等)
Request.referrer 只读
请求的来源 (例如:client).
Request.mode 只读
请求的模式 (例如: cors, no-cors, same-origin).
Request.credentials 只读
请求的凭证 (例如: omit, same-origin).
Request.redirect 只读
如何处理重定向模式 (例如: follow, error, or manual)
Request.integrity 只读
请求内容的 subresource integrity 值 (例如: sha256-BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE=).
Request.cache 只读
请求的缓存模式 (例如: default, reload, no-cache).
Request implements Body, so it also has the following property available to it:
Body.bodyUsed 只读
指示body是否被使用, 类型为Boolean
body请求正文
不管是请求还是响应都能够包含body对象. body也可以是以下任意类型的实例.
ArrayBuffer
ArrayBufferView (Uint8Array and friends)
Blob/File
string
URLSearchParams
FormData
Body 类定义了以下方法 (这些方法都被 Request 和Response所实现)以获取body内容. 这些方法都会返回一个被解析后的promise对象和数据.
Body.bodyUsed 只读
包含一个指示body是否被读取过的 Boolean 值。
方法Edit
Body.arrayBuffer()
使用一个buffer数组来读取 Response流中的数据,并将bodyUsed状态改为已使用。
Body.blob()
使用一个Blob对象来读取 Response流中的数据,并将bodyUsed状态改为已使用。【二进制】
Body.formData()
使用一个 FormData 对象来读取 Response流中的数据,并将bodyUsed状态改为已使用【表单数据】。
Body.json()
使用一个 JSON 对象来读取 Response流中的数据,并将bodyUsed状态改为已使用【json】。
Body.text()
使用一个USVString (文本)
clone() 方法The clone() method of the Request interface creates a copy of the current Request object.
clone() throws a TypeError if the response Body has already been used. In fact, the main reason clone() exists is to allow multiple uses of Body objects (when they are one-use only.)
对象来读取 Response流中的数据,并将bodyUsed状态改为已使用。比起XHR来,这些方法让非文本化的数据使用起来更加简单,因为这些方法都被 Request 和Response所实现。
返回 response
如果遇到网络故障,fetch() promise 将会 reject,带上一个 TypeError 对象。虽然这个情况经常是遇到了权限问题或类似问题——比如 404 不是一个网络故障。想要精确的判断 fetch() 是否成功,需要包含 promise resolved 的情况,此时再判断 Response.ok 是不是为 true。
response的属性和方法:
Response.type 只读
包含Response的类型 (例如, basic, cors).
Response.url 只读
包含Response的URL.
Response.useFinalURL
包含了一个布尔值来标示这是否是该Response的最终URL.
Response.status 只读
包含Response的状态码 (例如, 200 成功).
Response.ok 只读
包含了一个布尔值来标示该Response成功(状态码200-299) 还是失败.
Response.statusText 只读
包含了与该Response状态码一致的状态信息 (例如, OK对应200).
Response.headers 只读
包含此Response所关联的Headers 对象.
Response 实现了 Body, 所以以下属性同样可用:
Body.bodyUsed 只读
包含了一个布尔值来标示该Response是否读取过Body.
Response.clone()
创建一个Response对象的克隆
Response.error()
返回一个绑定了网络错误的新的Response对象
Response.redirect()
用另一个URL创建一个新的 response.
Response 实现了 Body, 所以以下方法同样可用