一、Fetch API

1、简介

Fetch API提供了一个获取资源的接口(包括跨域请求),等同于XMLHttpRequest,是一个现代的概念。它提供了许多与XMLHttpRequest相同的功能,但被设计成更具可扩展性和高效性。Fetch的核心在于对HTTP接口:Headers、Request、Response、Body等的抽象,以及用于初始化请求异步资源的全局fetch()方法。除此之外,Fetch还利用了请求的异步特性–它是基于Promise的。

2、特性检测

可以通过判断HeadersRequestResponsefetch()是否在Window或Worker域中来检测Fetch API的支持情况:

if(fetch){
	//支持,使用fetch发送请求
}else{
	//不支持,使用XMLHttpRequest
}

二、Headers

可以使用Headers接口获取HTTP请求和响应头,并对其执行添加、删除等操作。Headers对象有一个关联的头列表,该列表由零个或多个键值对组成,初始为空。可以通过Request.headersResponse.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表示响应/请求的正文,允许声明它的内容类型以及如何处理它。

RequestResponse都实现了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

      请求的方法,例如:GETPOST等。

    • headers

      请求头

    • body

      请求体(GET和HEAD请求没有body)

    • mode

      请求的模式,例如:corsno-corssame-originnevigate

    • credentials

      用户代理在跨域请求中是否从其他域发送cookies,可取值为:omitsame-origininclude

    • cache

      请求中使用的缓存模式

    • redirect

      对重定向的处理方式

    • referrer

      请求的来源,可取值为:clientno-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

[只读]请求的方法,例如:GETPOST等。

  • url

[只读]请求的URL

  • headers

[只读]请求头,是一个Headers对象。

  • referrerreferrerPolicy

[只读]请求来源和请求来源策略

  • 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-CookieSet-Cookie2之外的所有头信息。

    • cors

    跨域请求的响应,可以访问某些headers和body。

    • error

    网络错误,没有描述错误的有用信息,响应的状态status为0,headers为空且不可变。这是一种从Response.error()获得的响应类型。

    • opaque

    no-cors类型请求跨域资源的响应。

    • opaqueredirect

    redirectmanual类型请求的响应,响应状态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);
});
附: