Appearance
Fetch
用于在 JavaScript 里发出 HTTP 请求。
javascript
fetch(url, options)options
method 请求方法
"GET"
...
headers 请求头
{ "Content-Type": "text/plain;charset=UTF-8" }
body 请求体
'foo=foo&bar=bar'
formData
...
referrer 设置 referer 标头,可以为任意字符串,也可以设为空字符串 (即不发送referer标头)。
"about:client",
referrerPolicy 用于设定Referer标头的规则。
属性可能的取值如下:
no-referrer-when-downgrade:默认值,总是发送Referer标头,除非从 HTTPS 页面请求 HTTP 资源时不发送。
no-referrer:不发送Referer标头。
origin:Referer标头只包含域名,不包含完整的路径。
origin-when-cross-origin:同源请求Referer标头包含完整的路径,跨域请求只包含域名。
same-origin:跨域请求不发送Referer,同源请求发送。
strict-origin:Referer标头只包含域名,HTTPS 页面请求 HTTP 资源时不发送Referer 标头。
strict-origin-when-cross-origin:同源请求时Referer标头包含完整路径,跨域请求时 只包含域名。
HTTPS:页面请求 HTTP 资源时不发送该标头。
unsafe-url:不管什么情况,总是发送Referer标头。
mode
cors:默认值,允许跨域请求。
same-origin:只允许同源请求。
no-cors:请求方法只限于 GET、POST 和 HEAD,并且只能使用有限的几个简单标头,不能添 加跨域的复杂标头,相当于提交表单所能发出的请求。
credentials
same-origin:默认值,同源请求时发送 Cookie,跨域请求时不发送。
include:不管同源请求,还是跨域请求,一律发送 Cookie。
omit:一律不发送。
cache: "default",
default:默认值,先在缓存里面寻找匹配的请求。
no-store:直接请求远程服务器,并且不更新缓存。
reload:直接请求远程服务器,并且更新缓存。
no-cache:将服务器资源跟本地缓存进行比较,有新的版本才使用服务器资源,否则使用缓存。
force-cache:缓存优先,只有不存在缓存的情况下,才请求远程服务器。
only-if-cached:只检查缓存,如果缓存里面不存在,将返回504错误。
redirect: "follow",
follow:默认值,fetch()跟随 HTTP 跳转。
error:如果发生跳转,fetch()就报错。
manual:fetch()不跟随 HTTP 跳转,但是response.url属性会指向新的 URL, response.redirected属性会变为true,由开发者自己决定后续如何处理跳转。
integrity: "",
属性指定一个哈希值,用于检查 HTTP 回应传回的数据是否等于这个预先设定的哈希值。 比如,下载文件时,检查文件的 SHA-256 哈希值是否相符,确保没有被篡改。
keepalive: false,
用于页面卸载时,告诉浏览器在后台保持连接,继续发送数据。
signal: undefined
指定一个 AbortSignal 实例,用于取消fetch()请求。
GET
javascript
fetch('https://api.github.com/users/xnorain001')
.then(response => {
console.log(response)
/*
Response对象根据服务器返回的不同类型的数据,提供了不同的读取方法。
response.text():得到文本字符串, 比如 HTML 文件。
response.json():得到 JSON 对象。
response.blob():得到二进制 Blob 对象。
response.formData():得到 FormData 表单对象, 主要用在 Service Worker 里面,拦截用户提交的表单,修改某些数据以后,再提交给服务器。
response.arrayBuffer():得到二进制 ArrayBuffer 对象, 主要用于获取流媒体文件。
上面5个读取方法都是异步的,返回的都是 Promise 对象。必须等到异步操作结束,才能得到服务器返回的完整数据。
Stream 对象只能读取一次,读取完就没了。这意味着,前一节的五个读取方法,只能使用一个,否则会报错。
let text = await response.text();
let json = await response.json(); // 报错
先使用了response.text(),就把 Stream 读完了。后面再调用response.json(),就没有内容可读了,所以报错。
response.clone()方法,创建Response对象的副本,实现多次读取。
response.redirect()方法,用于将 Response 结果重定向到指定的 URL。该方法一般只用在 Service Worker 里面。
response.body可以用来分块读取内容,应用之一就是显示下载的进度。
const response = await fetch('flower.jpg');
const reader = response.body.getReader();
while(true) {
const {done, value} = await reader.read();
if (done) {
break;
}
console.log(`Received ${value.length} bytes`)
}
response.body.getReader()方法返回一个遍历器。这个遍历器的read()方法每次返回一个对象,表示本次读取的内容块。
这个对象的done属性是一个布尔值,用来判断有没有读完;value属性是一个 arrayBuffer 数组,表示内容块的内容,而value.length属性是当前块的大小。
*/
}, reason => {
console.log(reason)
})fetch 的响应(Response对象)
body: ReadableStream
暴露响应的流
bodyUsed: false
该 body 是否被使用过
headers: {}
响应头
Headers.get():根据指定的键名,返回键值。
Headers.has(): 返回一个布尔值,表示是否包含某个标头。
Headers.set():将指定的键名设置为新的键值,如果该键名不存在则会添加。
Headers.append():添加标头。
Headers.delete():删除标头。
Headers.keys():返回一个遍历器,可以依次遍历所有键名。
for(let key of Headers.keys()) { console.log(key); }
Headers.values():返回一个遍历器,可以依次遍历所有键值。
Headers.entries():返回一个遍历器,可以依次遍历所有键值对([key, value])。
Headers.forEach():依次遍历标头,每个标头都会执行一次参数函数。
ok: true
HTTP 响应状态码范围
[200, 300)时为 true, 其他情况为 false。redirected: false
请求是否发生过跳转
status: 200
HTTP 响应状态码
statusText: "OK"
HTTP 响应的状态信息
type: "cors"
请求类型
basic:普通请求,即同源请求。
cors:跨域请求。
error:网络错误,主要用于 Service Worker。
opaque:如果 fetch() 请求的 type 属性设为 no-cors ,就会返回这个值,详见请求 部分。表示发出的是简单的跨域请求,类似
<form>表单的那种跨域请求。opaqueredirect:如果fetch()请求的redirect属性设为manual,就会返回这个值。
url: "https://api.github.com/users/xnorain001"
请求url, 如果有跳转, 是最终的url
成功
fetch 请求只有网络错误,或者无法连接时,fetch() 才会报错,其他情况都不会报错,而是认为 请求成功。即使服务器返回的状态码是 4xx 或 5xx,fetch() 也不会报错(即 Promise 不会变 为 rejected 状态)。可以通过 Response.status 属性,得到 HTTP 回应的真实状态码,判断 请求是否成功。不用考虑网址跳转(状态码为 3xx),因为 fetch() 会将跳转的状态码自动转为 200。
javascript
if (response.status >= 200 && response.status < 300) {
// ...
} else {
// ...
}
// 也可以通过 response.ok 是否为 true 判断成功
if (response.ok) {
// 请求成功
} else {
// 请求失败
}取消
javascript
// 首先新建 AbortController 实例
let controller = new AbortController();
let signal = controller.signal;
// 然后发送fetch()请求
fetch(url, {
// 配置对象的signal属性必须指定接收 AbortController 实例发送的信号controller.signal。
signal: controller.signal
});
signal.addEventListener('abort',
() => console.log('abort!')
);
// controller.abort()方法用于发出取消信号。这时会触发abort事件,这个事件可以监听,
// 也可以通过controller.signal.aborted属性判断取消信号是否已经发出。
controller.abort(); // 取消
console.log(signal.aborted); // true
// 1秒后自动取消请求的例子
let controller = new AbortController();
setTimeout(() => controller.abort(), 1000);
try {
let response = await fetch('/long-operation', {
signal: controller.signal
});
} catch(err) {
if (err.name == 'AbortError') {
console.log('Aborted!');
} else {
throw err;
}
}