Fetch API 提供了一个 JavaScript 接口, 用于发起http请求。是浏览器自带的JavaScript API。
和XMLHttpRequest
一样,都是用来跨网络异步获取资源。但fetch
比起XMLHttpRequest()
使用起来更简洁、方便
。
有一些差别,具体如下:
1.
fetch()
使用 Promise ,不使用回调函数,因此大大简化了写法,写起来更简洁。
2.
fetch()
采用模块化设计,API 分散在多个对象上(Response 对象、Request 对象、Headers 对象),更合理一些;相比之下,XMLHttpRequest 的 API 设计并不是很好,输入、输出、状态都在同一个接口管理,容易写出非常混乱的代码
3.
fetch()
通过数据流(Stream 对象)处理数据,可以分块读取,有利于提高网站性能表现,减少内存占用,对于请求大文件更实用。而XMLHTTPRequest
对象不支持数据流,所有的数据必须放在缓存里,不支持分块读取,必须等待全部拿到后,再一次读出来。
4. 从
fetch()
返回的 Promise 不会被标记为 reject, 即使响应的 HTTP 状态码是 404 或 500。相反,它会将 Promise 状态标记为 resolve (但是会将 resolve 的返回值的ok
属性设置为 false ),仅当网络故障时或请求被阻止时,才会标记为 reject。
5.
fetch
默认不会发送 cookies。除非你使用了credentials 的初始化选项。
一. 基本使用
fetch()
接受一个 URL 字符串作为参数,默认向该网址发出 GET 请求,返回一个 Promise 对象。
fetch('http://example.com/movies.json')
.then(function(response) {
return response.json();
})
.then(function(myJson) {
console.log(myJson);
})
.catch(function(error) {
console.log(error)
})
复制代码
上面示例中,fetch()
接收到的response
是一个 Stream 对象,response.json()
是一个异步操作,取出所有内容,并将其转为 JSON 对象。
也可以传入第二个可选参数,用来配置 初始化
对象,(详细配置参考: 文档):
fetch(url, {
body: JSON.stringify(data),
headers: {
'content-type': 'application/json'
},
method: 'POST'
})
.then(response => response.json())
.then(data => {
console.log(data)
})
复制代码
二. Response对象
fetch()
请求成功以后,得到的是一个 Response 对象。它对应服务器的 HTTP 回应。
const response = await fetch(url);
复制代码
response 包含的数据通过 Stream 接口异步读取,但是它还包含一些同步属性,对应 HTTP 回应的标头信息(Headers),可以立即读取。
async function fetchRequest() {
const response = await fetch(url);
console.log(response.status);
console.log(response.statusText);
}
复制代码
上面示例中,response.status
和response.statusText
就是 Response 的同步属性,可以立即读取。
response 有以下属性:
Response.ok
属性返回一个布尔值,表示请求是否成功,true
对应 HTTP 请求的状态码 200 到 299,false
对应其他的状态码
Response.status
属性返回一个数字,表示 HTTP 回应的状态码(例如200,表示成功请求)
Response.statusText
属性返回一个字符串,表示 HTTP 回应的状态信息(例如请求成功以后,服务器返回”OK”)
Response.url
属性返回请求的 URL。如果 URL 存在跳转,该属性返回的是最终 URL。
Response.type
属性返回请求的类型。可能的值如下:
basic
:普通请求,即同源请求。cors
:跨域请求。error
:网络错误。
Response.redirected
属性返回一个布尔值,表示请求是否发生过跳转。
Response.headers 属性:
Response.headers
属性,指向一个 Headers 对象,对应 HTTP 回应的所有标头。
Headers 对象可以使用for...of
循环进行遍历。
const response = await fetch(url);
for (let [key, value] of response.headers) {
console.log(`${key} : ${value}`);
}
复制代码
Headers 对象提供了以下方法,用来操作标头:
Headers.get()
:根据指定的键名,返回键值。Headers.has()
: 返回一个布尔值,表示是否包含某个标头。Headers.set()
:将指定的键名设置为新的键值,如果该键名不存在则会添加。Headers.append()
:添加标头。Headers.delete()
:删除标头。Headers.keys()
:返回一个遍历器,可以依次遍历所有键名。Headers.values()
:返回一个遍历器,可以依次遍历所有键值。Headers.entries()
:返回一个遍历器,可以依次遍历所有键值对([key, value]
)。Headers.forEach()
:依次遍历标头,每个标头都会执行一次参数函数。
这些方法中,最常用的是response.headers.get()
,用于读取某个标头的值。
let response = await fetch(url);
response.headers.get('Content-Type')
// application/json; charset=utf-8
复制代码
Headers.keys()
和Headers.values()
方法用来分别遍历标头的键名和键值
// 键名
for(let key of myHeaders.keys()) {
console.log(key);
}
// 键值
for(let value of myHeaders.values()) {
console.log(value);
}
复制代码
读取Response
对象的方法:
Response
对象根据服务器返回的不同类型的数据,提供了不同的读取方法。
response.text()
:得到文本字符串。response.json()
:得到 JSON 对象。response.blob()
:得到二进制 Blob 对象。response.formData()
:得到 FormData 表单对象。response.arrayBuffer()
:得到二进制 ArrayBuffer 对象。
注意: 上面5个读取方法都是异步的,返回的都是 Promise 对象。
Response.clone() 方法
Stream 对象只能读取一次,读取完就没了。这意味着,前一节的五个读取方法,只能使用一个,否则会报错。
let text = await response.text();
let json = await response.json(); // 报错
复制代码
上面示例先使用了response.text()
,就把 Stream 读完了。后面再调用response.json()
,就没有内容可读了,所以报错。
Response 对象提供Response.clone()
方法,创建Response
对象的副本,实现多次读取。
const response1 = await fetch('flowers.jpg');
const response2 = response1.clone();
const myBlob1 = await response1.blob();
const myBlob2 = await response2.blob();
image1.src = URL.createObjectURL(myBlob1);
image2.src = URL.createObjectURL(myBlob2);
复制代码
上面示例中,response.clone()
复制了一份 Response 对象,然后将同一张图片读取了两次。
Response.body 属性
Response.body
属性是 Response 对象暴露出的底层接口,返回一个 ReadableStream 对象,供用户操作。
三: fetch()完整 API
fetch()
第二个参数的完整 API 如下。
const response = fetch(url, {
method: "GET",
headers: {
"Content-Type": "text/plain;charset=UTF-8"
},
body: undefined,
referrer: "about:client",
referrerPolicy: "no-referrer-when-downgrade",
mode: "cors",
credentials: "same-origin",
cache: "default",
redirect: "follow",
integrity: "",
keepalive: false,
signal: undefined
});
复制代码
cache
cache
属性指定如何处理缓存。可能的取值如下:
default
:默认值,先在缓存里面寻找匹配的请求。no-store
:直接请求远程服务器,并且不更新缓存。reload
:直接请求远程服务器,并且更新缓存。no-cache
:将服务器资源跟本地缓存进行比较,有新的版本才使用服务器资源,否则使用缓存。force-cache
:缓存优先,只有不存在缓存的情况下,才请求远程服务器。only-if-cached
:只检查缓存,如果缓存里面不存在,将返回504错误。
mode
mode
属性指定请求的模式。可能的取值如下:
cors
:默认值,允许跨域请求。same-origin
:只允许同源请求。no-cors
:请求方法只限于 GET、POST 和 HEAD,并且只能使用有限的几个简单标头,不能添加跨域的复杂标头,相当于提交表单所能发出的请求。
credentials
credentials
属性指定是否发送 Cookie。可能的取值如下:
same-origin
:默认值,同源请求时发送 Cookie,跨域请求时不发送。include
:不管同源请求,还是跨域请求,一律发送 Cookie。omit
:一律不发送。
跨域请求发送 Cookie,需要将credentials
属性设为include
。
fetch('http://another.com', { credentials: "include" }); 复制代码
signal
signal
属性指定一个 AbortSignal 实例,用于取消fetch()
请求
redirect
redirect
属性指定 HTTP 跳转的处理方法。可能的取值如下:
follow
:默认值,fetch()
跟随 HTTP 跳转。error
:如果发生跳转,fetch()
就报错。manual
:fetch()
不跟随 HTTP 跳转,但是response.url
属性会指向新的 URL,response.redirected
属性会变为true
,由开发者自己决定后续如何处理跳转。
以上就是fetch API 的全部内容。
参考:
1. 阮一峰网络日志
2. MDN