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