JavaScript Fetch API
一、Fetch API
1、简介
Fetch API提供了一个获取资源的接口(包括跨域请求),等同于XMLHttpRequest,是一个现代的概念。它提供了许多与XMLHttpRequest相同的功能,但被设计成更具可扩展性和高效性。Fetch的核心在于对HTTP接口:Headers、Request、Response、Body等的抽象,以及用于初始化请求异步资源的全局fetch()
方法。除此之外,Fetch还利用了请求的异步特性–它是基于Promise的。
2、特性检测
可以通过判断Headers
、Request
、Response
或fetch()
是否在Window或Worker域中来检测Fetch API的支持情况:
if(fetch){
//支持,使用fetch发送请求
}else{
//不支持,使用XMLHttpRequest
}
二、Headers
可以使用Headers接口获取HTTP请求和响应头,并对其执行添加、删除等操作。Headers对象有一个关联的头列表,该列表由零个或多个键值对组成,初始为空。可以通过Request.headers
或Response.headers
获取Headers对象,通过Headers.Headers()
创建Headers对象。
Headers对象有一个特殊的guard属性,这个属性没有暴露出来,但是它会影响Headers对象的哪些内容可以被操作(set()
、append()
、delete()
):
Headers()
当使用Headers()
创建一个新的Headers对象时,它的guard为默认值’none’。
Request()
如果使用Request()
创建一个新的Request对象时,它关联的Headers对象的guard为’request’。
如果在创建Request()
时,mode
设置为no-cors
,则与Request对象关联的Headers对象的guard为’request-no-cors’。
Response()
如果使用Response()
创建一个新的Response对象时,它关联的Headers对象的guard为’response’。
如果是使用Response.error()
或Response.redirect()
方法创建Response对象,则与Response对象关联的Headers对象的guard为’immutable’。
1、语法
创建一个新的Headers对象:
var myHeaders = new Headers(init);
其中参数init
是可选的,可以在创建Headers对象时初始化某些消息头的值。
- 示例
let config = {
'Content-Type': 'image/jpeg',
'Accept-Charset': 'utf-8'
};
let myHeaders = new Headers(config);
console.log(myHeaders.get('Content-Type'));//image/jpeg
console.log(myHeaders.get('Accept-Encoding'));//null
2、方法
append()
myHeaders.append(name,value);
添加一个消息头。
let myHeaders = new Headers();
myHeaders.append('Content-Type', 'image/jpeg');
console.log(myHeaders.get('Content-Type'));//image/jpeg
myHeaders.append('Accept-Encoding', 'deflate');
myHeaders.append('Accept-Encoding', 'gzip');
console.log(myHeaders.get('Accept-Encoding'));//deflate, gzip
set()
myHeaders.set(name, value);
添加或替换一个消息头。
let myHeaders = new Headers();
myHeaders.set('Content-Type', 'image/jpeg');
console.log(myHeaders.get('Content-Type'));//image/jpeg
myHeaders.set('Accept-Encoding', 'deflate');
myHeaders.set('Accept-Encoding', 'gzip');
console.log(myHeaders.get('Accept-Encoding'));//gzip
get()
myHeaders.get(name);
获取Headers对象中指定的消息头的值,如果存在多个值,则返回第一个。
delete()
myHeaders.delete(name);
删除Headers对象中指定的消息头。
let myHeaders = new Headers();
myHeaders.append('Content-Type', 'image/jpeg');
console.log(myHeaders.get('Content-Type'));//image/jpeg
myHeaders.delete('Content-Type');
console.log(myHeaders.get('Content-Type'));//null
keys()
返回Headers对象中所有消息头名称。
let myHeaders = new Headers();
myHeaders.append('Content-Type', 'image/jpeg');
myHeaders.append('Accept-Encoding', 'gzip');
for(let key of myHeaders.keys()){
console.log(key);
}
输出:
accept-encoding
content-type
values()
返回Headers对象中所有消息头的值。
let myHeaders = new Headers();
myHeaders.append('Content-Type', 'image/jpeg');
myHeaders.append('Accept-Encoding', 'gzip');
for(let value of myHeaders.values()){
console.log(value);
}
输出:
gzip
image/jpeg
entries()
返回Headers对象中所有消息头的键值对。
let myHeaders = new Headers();
myHeaders.append('Content-Type', 'image/jpeg');
myHeaders.append('Accept-Encoding', 'gzip');
for(let pair of myHeaders.entries()){
console.log(pair);
}
输出:
["accept-encoding", "gzip"]
["content-type", "image/jpeg"]
has()
myHeaders.has(name);
判断Headers对象中是否存在指定的消息头。
let myHeaders = new Headers();
myHeaders.append('Content-Type', 'image/jpeg');
console.log(myHeaders.has('Content-Type'));//true
console.log(myHeaders.has('Referer'));//false
三、Body
Fetch API中的Body表示响应/请求的正文,允许声明它的内容类型以及如何处理它。
Request
和Response
都实现了Body
,因此给这两个对象提供了一个相关联的body(字节流)、已使用的标志和MIME类型。
1、属性
bodyUsed
只读属性,表示该body是否被使用过。
var used = response.bodyUsed;
fetch('http://www.example.com/courage.json').then(function(response){
console.log(response.bodyUsed);
response.json();
console.log(response.bodyUsed);
});
2、方法
arrayBuffer()
使用一个Buffer数组来读取Response
流中的数据,返回一个使用ArrayBuffer解决的Promise对象,并将bodyUsed
状态改为已使用。
response.arrayBuffer().then(function(buffer) {
// do something with buffer
});
blob()
读取Response
流中的数据,返回一个使用Blob解决的Promise对象,并将bodyUsed
状态改为已使用。
response.blob().then(function(myBlob) {
// do something with myBlob
});
formData()
读取Response
流中的数据,返回一个使用FormData解决的Promise对象,并将bodyUsed
状态改为已使用。
response.formData().then(function(formdata) {
// do something with your formdata
});
json()
读取Response
流中的数据,返回一个使用JSON解决的Promise对象,并将bodyUsed
状态改为已使用。
response.json().then((data) => {
// do something with your data
});
text()
读取Response
流中的数据,返回一个使用文本解决的Promise对象,并将bodyUsed
状态改为已使用。
response.text().then(function (text) {
// do something with the text response
});
四、Request
可以使用Request.Request()
构造函数创建一个Request对象,也可以是其他API操作返回的值。
1、语法
var myRequest = new Request(input, init);
参数说明:
input
想要获取的资源,可以是资源的URL或一个Request对象。
-
init
可选,值为希望包含在请求中的自定义选项,常用的选项如下:
-
method
请求的方法,例如:
GET
、POST
等。 -
headers
请求头
-
body
请求体(GET和HEAD请求没有body)
-
mode
请求的模式,例如:
cors
、no
-cors
、same
-origin
、nevigate
。 -
credentials
用户代理在跨域请求中是否从其他域发送cookies,可取值为:
omit
、same-origin
、include
。 -
cache
请求中使用的缓存模式
-
redirect
对重定向的处理方式
-
referrer
请求的来源,可取值为:
client
、no-referrer
或一个URL。 -
integrity
资源完整性校验值
-
示例:
let myRequest = new Request('flowers.jpg');
let myHeaders = new Headers();
myHeaders.append('Content-Type', 'image/jpeg');
let config = {
method: 'GET',
headers: myHeaders,
mode: 'cors',
cache: 'default'
};
let myRequest = new Request('flowers.jpg', config);
let config = {
method: 'GET',
headers: {
'Content-Type': 'image/jpeg'
},
mode: 'cors',
cache: 'default'
};
let myRequest = new Request('flowers.jpg', config);
let copy = new Request(myRequest);
2、属性
method
[只读]请求的方法,例如:GET
、POST
等。
url
[只读]请求的URL
headers
[只读]请求头,是一个Headers对象。
referrer
和referrerPolicy
[只读]请求来源和请求来源策略
-
mode
[只读]请求的模式,可取以下值:
same-origin
此模式为发送同源请求。
cors
允许跨域请求。
no-cors
此模式下要求请求的方法是HEAD、GET或POST,而且JavaScript不能访问响应结果
Response
的任何属性。navigate
一种支持导航的模式,仅供HTML文档之间的导航请求使用。
-
credentials
[只读]表示用户代理在跨域请求中是否从其他域发送cookies,可取以下值:
omit
不发送
same-origin
同源时才发送cookies、HTTP Basic authentication等验证信息。
inclue
总是发送所请求域在本地的cookies、HTTP Basic authentication等验证信息。
-
redirect
[只读]如何处理重定向,可取以下值:
-
follow
-
error
-
manual
-
-
integrity
[只读]请求资源的完整性校验值(例如:sha256-BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE=
)。
-
cache
[只读]请求的缓存模式,控制如何与浏览器的HTTP缓存交互,可取以下值:
- default
浏览器从HTTP缓存中寻找匹配的请求,如果匹配且有效,则从缓存返回;如果匹配但无效,则发送一个条件请求(conditional request)询问服务器资源是否有效,如果有效,则从缓存中返回;否则,重新从服务器下载资源并更新缓存。如果一开始缓存中就没有匹配的,则直接下载资源并缓存。
- no-store
直接从远程服务器获取资源,并不会使用获取到的资源更新缓存
- no-cache
浏览器从HTTP缓存中寻找匹配的请求,如果有匹配的,不论是否有效,都会向服务器发送一个条件请求(conditional request)询问服务器资源是否有效,如果有效,则从缓存中返回;否则,重新从服务器下载资源并更新缓存。如果一开始缓存中就没有匹配的,则直接下载资源并缓存。
- force-cache
浏览器从HTTP缓存中寻找匹配的请求,如果有匹配的,不论是否有效,都从缓存中返回。如果没有匹配,直接下载资源并缓存。
- only-if-cached
此种模式只能用于同源(same-origin)请求。浏览器从HTTP缓存中寻找匹配的请求,如果有匹配的,不论是否有效,都从缓存中返回。如果没有匹配,浏览器将返回错误。
-
bodyUsed
[只读]同Body的bodyUsed属性。
3、方法
clone()
创建一个当前Request对象的副本。
var newRequest = request.clone();
- 与Body相同的方法
由于Request实现自Body,因此它也有以下方法:arrayBuffer()
、blob()
、formData()
、json()
、text()
五、Response
1、语法
var myResponse = new Response(body, init);
参数说明:
- body
可选,指定响应的内容
-
init
可选,表示设置到response对象上的自定义设置(options):
- status
响应状态码,例如:200。
- statusText
和状态码关联的状态消息,例如:OK。
- headers
响应消息头,一个Headers对象或key/value键值对。
示例:
let options = {
status: 200,
statusText: 'success!'
};
let myResponse = new Response('Hello World!', options);
2、属性
headers
[只读]响应头,是一个Headers对象。
status
[只读]响应的状态码,例如成功时为200。
statusText
[只读]表示与状态码对应的状态消息。
ok
[只读]表示响应是否成功的布尔值(状态码为200 ~ 209)。
-
type
[只读]响应类型,可取以下值:
- basic
正常类型,同源响应,带有除了
Set-Cookie
和Set-Cookie2
之外的所有头信息。- cors
跨域请求的响应,可以访问某些headers和body。
- error
网络错误,没有描述错误的有用信息,响应的状态status为0,headers为空且不可变。这是一种从
Response.error()
获得的响应类型。- opaque
对
no-cors
类型请求跨域资源的响应。- opaqueredirect
对
redirect
为manual
类型请求的响应,响应状态status为0,headers和body为空。 -
url
[只读]响应的URL,此属性值是重定向后获得的最终URL。
redirected
[只读]指示响应是否是由于重定向的请求产生的。
bodyUsed
[只读]同Body的bodyUsed属性。
3、方法
clone()
创建一个响应对象的克隆。
var newResponse = response.clone();
error()
返回一个绑定了网络错误的新Response对象。
redirect()
返回一个重定向到指定URL的Response对象。
- 与Body相同的方法
由于Response实现自Body,因此它也有以下方法:arrayBuffer()
、blob()
、formData()
、json()
、text()
六、fetch
可以使用fetch()
方法发送请求或获取资源,此方法必须接受一个资源路径的参数。无论请求成功与否,都会返回一个Promise对象。
使用fetch()
如果接收到一个代表错误的HTTP状态码,即使响应状态码是404或500,它返回的Promise对象也不会被reject而是正常的resolve(响应的ok属性仍为false)。仅当网络故障或请求被阻止时,才会被reject。
默认情况下,fetch()
不会从服务器发送或接收任何cookies。
1、语法
Promise<Response> fetch(input[, init]);
参数与Request()
构造方法的参数一样。
2、示例
- 示例一
从网络中请求JSON文件并打印到控制台:
fetch('http://www.example.com/Web/movies.json').then((response) => {
return response.json();
}).then((json) => {
console.log(json);
});
- 示例二
带配置项的请求:
let data = {type: 'addTodo', value: 'exercising'};
let options = {
method: 'POST',
body: JSON.stringify(data),
cache: 'no-cache',
credentials: 'same-origin',
headers: {'Content-Type': 'application/json'},
mode: 'cors',
redirect: 'follow',
referrer: 'no-referrer'
};
fetch('http://www.example.com/Web/deal', options).then((response) => {
return response.json();
}).then((data) => {
console.log(data);
});
- 示例三:
检测请求是否成功:
fetch('favicon.ico').then(response => {
if(response.ok){
return response.blob();
}
throw new Error('Network response was not ok.');
}).then(data => {
let url = URL.createObjectURL(data);
document.querySelector('#myImg').src = url;
}).catch(error => {
console.log(error.message);
});
- 示例四
自定义请求对象:
let headers = new Headers();
headers.append('Content-Type', 'text/html');
let options = {
method: 'GET',
headers,
mode: 'cors',
cache: 'default'
};
let request = new Request('getTodo', options);
fetch(request).then(response => {
return response.text();
}).then(text => {
console.log(text);
});