Fetch API
Fetch API 提供了一个获取资源的接口(包括跨网络通信)。对于任何使用过 XMLHttpRequest
的人都能轻松上手,而且新的 API 提供了更强大和灵活的功能集。
备注: 此特性在 Web Worker中可用
概念和用法
Fetch 提供了对 Request
和 Response
(以及其他与网络请求有关的)对象的通用定义。这将在未来更多需要它们的地方使用它们,无论是 service worker、Cache API,又或者是其他处理请求和响应的方式,甚至是任何一种需要你自己在程序中生成响应的方式(即使用计算机程序或者个人编程指令)。
它同时还为有关联性的概念,例如 CORS
和 HTTP Origin
标头信息,提供一种新的定义,取代它们原来那种分离的定义。
发送请求或者获取资源,请使用 fetch()
方法。它在很多接口中都被实现了,更具体地说,是在 Window
和 WorkerGlobalScope
接口上。因此在几乎所有环境中都可以用这个方法获取资源。
fetch()
强制接受一个参数,即要获取的资源的路径。它返回一个 Promise
,该 Promise 会在服务器使用标头响应后,兑现为该请求的 Response
——即使服务器的响应是 HTTP 错误状态。你也可以传一个可选的第二个参数 init
。
一旦 Response
被返回,有许多方法可以获取主体定义的内容以及如何处理它。
你也可以通过 Request()
和 Response()
构造函数直接创建请求和响应。但是我们不建议这么做,它们更可能被创建为其他的 API 操作的结果(比如,service worker 中的 FetchEvent.respondWith
。
与 jQuery 的区别
fetch
规范主要在三个方面与 jQuery.ajax()
不同:
-
从
fetch()
返回的 Promise 不会因 HTTP 的错误状态而被拒绝,即使响应是 HTTP404
或500
。相反,它将正常兑现(ok
状态会被设置为false
),并且只有在网络故障或者有任何阻止请求完成时,才拒绝。 -
除非你在init 对象中设置(去包含)credentials,否则
fetch()
将不会发送跨源 cookie
备注: 更多关于 Fetch API 的用法,参考使用 Fetch,以及一些概念 Fetch 基础概念。
中止 fetch
要中止未完成的 fetch()
,甚至 XMLHttpRequest
操作,请使用 AbortController
和 AbortSignal
接口。
Fetch 接口
-
fetch()
包含了fetch()
方法,用于获取资源。 -
Headers
表示响应/请求的标头信息,允许你查询它们,或者针对不同的结果做不同的操作。 -
Request
相当于一个资源请求。 -
Response
相当于请求的响应
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
的 connect-src
指令控制,而不是它请求的资源。
语法
Promise<Response> fetch(input[, init]);
参数
-
?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
(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=
)。
返回值
一个 Promise
,resolve
时回传 Response
对象。
例外
类型 | 描述 |
---|---|
AbortError |
请求被AbortController.abort() 终止。 |
TypeError |
从Firefox 43开始,如果fetch() 接收到含有用户名和密码的 URL(例如http://user:password@example.com ),它将会抛出一个TypeError 。 |
示例
在 Fetch Request 示例
中,我们使用对应的构造器创建了一个新的 Request 对象,然后调用 fetch() 方法获取资源。因为我们是在请求一个图片,为了解析正常,我们对响应执行 [Body.blob
] 来设置相应的 MIME 类型。然后创建一个 Object URL,并元素中把它显示出来。
var myImage = document.querySelector('img');
var myRequest = new Request('flowers.jpg');
fetch(myRequest).then(function(response) {
return response.blob();
}).then(function(response) {
var objectURL = URL.createObjectURL(response);
myImage.src = objectURL;
});
在Fetch with init then Request 示例中,我们做同样的操作,除了在调用 fetch() 时传入一个 init 对象:
var myImage = document.querySelector('img');
var myHeaders = new Headers();
myHeaders.append('Content-Type', 'image/jpeg');
var myInit = { method: 'GET',
headers: myHeaders,
mode: 'cors',
cache: 'default' };
var myRequest = new Request('flowers.jpg');
fetch(myRequest,myInit).then(function(response) {
...
});
你也可以传入同样的 init 对象到 Request 构造器,来实现同样的效果,如:
var myRequest = new Request('flowers.jpg',myInit);
init
对象中的 headers
也可以是一个对象字面量:
var myInit = { method: 'GET',
headers: {
'Content-Type': 'image/jpeg'
},
mode: 'cors',
cache: 'default' };
var myRequest = new Request('flowers.jpg', myInit);