Fetch入门介绍
qingheluo2021-04-23清河洛473
fetch是一种在JavaScript脚本里面发出HTTP请求的方式,是XMLHttpRequest的一种替代方案fetch不是ajax的进一步封装,而是原生js,没有使用XMLHttpRequest对象fetch和XMLHttpRequest的不同点:1、fetch不使用回调函数,大大简化了写法
2、fetch返回的promise将不会拒绝http的错误状态,即使响应是一个HTTP404或者500
3、在默认情况下fetch不会接受或者发送cookies
4、fetch采用模块化设计,API分散在多个对象上(Response、Request、Headers、ReadableStream...
fetch是一种在JavaScript脚本里面发出HTTP请求的方式,是XMLHttpRequest的一种替代方案
fetch不是ajax的进一步封装,而是原生js,没有使用XMLHttpRequest对象
fetch和XMLHttpRequest的不同点:
1、fetch不使用回调函数,大大简化了写法
2、fetch返回的promise将不会拒绝http的错误状态,即使响应是一个HTTP404或者500
3、在默认情况下fetch不会接受或者发送cookies
4、fetch采用模块化设计,API分散在多个对象上(Response、Request、Headers、ReadableStream等),更合理
5、fetch通过数据流(Stream对象)异步处理数据,可以分块读取,有利于提高网站性能表现,减少内存占用,对于请求大文件或者网速慢的场景相当有用
fetch语法:fetch(url,option_obj)
option_obj是一个object对象,HTTP请求的方法、标头、数据体都在这个对象里面设置
method:请求的方法(string),可选值GET/POST/DELETE/PUT/HEAD等,默认GET
headers:请求标头(object),每个键值对为一个表头项目
body:请求的数据体
根据headers中的Content-Type值数据格式也要相应的变化
headers: {"Content-Type": "application/json;charset=UTF-8"}
body: JSON.stringify(data)
headers: {"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8"}
body: "key1=val1&key2=val2&.....&keyn=valn"
cache: 指定如何处理缓存,可能的值
default:默认值,先在缓存里面寻找匹配的请求
no-store:直接请求远程服务器,并且不更新缓存
reload:直接请求远程服务器,并且更新缓存
no-cache:将服务器资源跟本地缓存进行比较,有新的版本才使用服务器资源,否则使用缓存
force-cache:缓存优先,只有不存在缓存的情况下,才请求远程服务器
only-if-cached:只检查缓存,如果缓存里面不存在,将返回504错误
mode: 指定请求的模式,可能的值
cors:默认值,允许跨域请求
same-origin:只允许同源请求
no-cors:只限于GET、POST和HEAD方法,且只能使用有限的几个简单标头,不能添加跨域的复杂标头,相当于提交表单所能发出的请求。
跨源请求时,返回的表头中必须要有Access-Control-Allow-Origin表头,表示服务于允许跨域请求的域名(格式:http[s]://domain),星号表示允许所有,但是设置为星号会导致浏览器不发送cookies
请求表头中添加上Origin表头,指定请求的域名
credentials: 是否发送cookies,可能的值
same-origin:默认值,同源请求时发送Cookie,跨域时不发送
include:一律发送Cookie
omit:一律不发送
signal:指定一个 AbortSignal 实例,用于取消fetch()请求
keepalive:布尔值,页面卸载时浏览器是否在后台保持连接,继续发送数据
redirect: 指定 HTTP 跳转的处理方法,可能的值
follow:默认值,跟随HTTP跳转。
error:如果发生跳转,就报错
manual:不跟随HTTP跳转,但response.url属性会指向新的URL,response.redirected属性会变为true
integrity:指定一个哈希值,用于检查HTTP回应传回的数据是否等于这个预先设定的哈希值
integrity: 'sha256-abcdef'
referrer:设定来源网址
referrerPolicy:用于设定Referer标头的规则
no-referrer-when-downgrade:默认值,除从HTTPS页面请求HTTP时不发送,其他一律发送
no-referrer:一律不发送
origin:标头只包含域名,不包含完整的路径。
origin-when-cross-origin:同源请求包含完整的路径,跨域请求只包含域名
same-origin:跨域请求不发送,同源请求发送。
strict-origin:只包含域名,HTTPS页面请求HTTP时不发送
strict-origin-when-cross-origin:同源时包含完整路径,跨域时只包含域名,HTTPS页面请求 HTTP资源时不发送
unsafe-url:不管什么情况,总是发送Referer标头
在请求过程中中断请求
fetch()请求发送以后,如果中途想要取消,需要使用AbortController对象
//1、在fetch()请求之前创建一个AbortController对象
let controller = new AbortController();
//2、创建一个信号接收对象:signal对象
let signal = controller.signal;
//3、把该信号接收对象通过signal属性传递到fetch()请求中
fetch(url, {
signal: controller.signal
});
//接收信号对象接收取消信号后会触发abort事件
signal.addEventListener('abort',
() => console.log('abort!')
);
//4、AbortController对象的abort()方法发出取消信号
controller.abort(); // 取消
//发出取消信号后信号接收对象的aborted属性可以判断取消信号是否接收
console.log(signal.aborted); // true
fetch函数返回Response对象
Response对象的属性:
ok:布尔值,true对应HTTP状态码200到299,false对应其他的状态码
status:数字,表示HTTP状态码(3XX跳转状态码会自动转为200)
statusText:字符串,表示HTTP回应的状态码字符串信息。
url:请求的URL,如果存在跳转,返回的是最终URL
type属性返回请求的类型。可能的值如下:
basic:普通请求,即同源请求。
cors:跨域请求。
error:网络错误,主要用于Service Worker。
opaque:如果fetch()请求的type属性设为no-cors,就会返回这个值,表示发出的是简单的跨域请求
Response对象的方法:
text():得到文本字符串
json():得到 JSON 对象
blob():得到二进制Blob对象
formData():得到FormData表单对象
arrayBuffer():得到二进制ArrayBuffer对象
以上5个读取方法都是异步的,返回的都是Promise对象。
必须等到异步操作结束,才能得到服务器返回的完整数据。
而且5种方法一共只能使用一次,多次使用获取数据(即使不是一个方法)会报错
clone()可以创建一个Response对象副本(副本也只能读取一次),可以创建多个副本达到多次读取的目的
redirect():用于将Response结果重定向到指定的URL(一般用在Service Worker里面)
Response.headers指向一个Headers对象,对应HTTP回应的所有标头:
get(key):根据指定的标头名,返回对应的标头值
has(key): 返回一个布尔值,表示是否包含某个标头
set(key,value):将指定的标头设置为新的值,如果标头名不存在则会添加
append(key,value):添加标头
delete(key):删除标头
keys():返回一个遍历器,可以依次遍历所有标头名
values():返回一个遍历器,可以依次遍历所有标头值
entries():返回一个遍历器,可以依次遍历所有键值对([key, value])
forEach():依次遍历标头,每个标头都会执行一次参数函数
Response.body指向一个ReadableStream对象,可以用来分块读取内容
const response = await fetch('/test/down/notapad2.7z');
const reader = response.body.getReader();
let size=0;
while(true) {
//这个对象的done属性是一个布尔值,用来判断有没有读完;
//value属性是一个 arrayBuffer 数组,表示当前内容块的内容
const {done, value} = await reader.read();
if (done) {break;}
size=size+value.length;
console.log(`本次接收 ${value.length/1024} kb`)
}
console.log(`共计下载${size/1024}kb,${size/1024/1024}mb`)