浅析Fetch API
fetch()方法与XMLHttpRequest类似,fetch也可以发起ajax请求,但是与XMLHttpRequest不同的是,fetch方式使用promise,相比较XMLHttpRequest更加简洁。
一、Fetch是什么
1、Fetch 是一个现代的概念,等同于 XMLHttpRequest。它提供了许多与XMLHttpRequest相同的功能,但被设计成更具可扩展性和高效性。
Fetch 提供了对 Request 和 Response (以及其他与网络请求有关的)对象的通用定义。
Fetch 还利用到了请求的异步特性——它是基于 Promise 的。
2、Fetch API 提供的一组对象
window.fetch 函数只是 Fetch API 提供的众多接口中的一个,还有很多有用的对象:
- window.Headers
- window.Response
- window.Request
- ……
3、不需要依赖第三方库,就可以优雅地使用 AJAX
Fetch API 提供了能够用于操作一部分http的 JavaScript 接口,比如requests 和 responses,它同时也提供了一个全局的 fetch() 方法,能够简单的异步的获取资源。使用 window.fetch 函数可以代替以前的 $. ajax、$.get 和 $.post。
二、缘起
1、XMLHttpRequest
(1)所有的功能全部集中在同一个对象中,容易书写出混乱、不易维护的代码
(2)采用传统的事件驱动模式,无法适配新的Promise API
2、Fetch API
(1)并非取代AJAX,而是对AJAX传统 API的改进
(2)精细的功能分割:头部信息、请求信息、响应信息等均分布到不同的对象,更利于处理各种复杂的 AJAX 场景
(3)使用 Promise API,更利于异步代码的书写
(4)Fetch API 并非 ES6内容,而是属于 HTML5 新增 Web API
3、Fetch 是浏览器提供的原生 AJAX 接口。
由于原来的XMLHttpRequest不符合关注分离原则,且基于事件的模型在处理异步上已经没有现代的Promise等那么有优势。因此Fetch出现来解决这种问题。
二、基本使用
1、请求配置对象
- method: 字符串, 请求方法, 默认值是 GET
- headers: 对象, 请求头信息
- body: 请求体的内容, 必须匹配请求头中的 Content-Type
- mode: 字符串, 请求模式
- credentials: 如何携带凭据( cookie )
- cache: 配置缓存模式
- default: 表示 fetch 请求之前将检查下http的缓存
- no-store: 表示 fetch 请求将完全忽略 http 缓存的存在。这意味着请求之前将不再检查下http 的缓存, 拿到响应后, 它也不会更新 http 缓存
- no-cache: 如果存在缓存, 那么 fetch 将发送一个条件查询 request 和一个正常的 request, 拿到响应后, 它会更新 http 缓存.
- reload: 表示 fetch 请求之前将忽略 http 缓存的存在, 但是请求拿到响应后, 它将主动更新 http 缓存
- force-cache: 表示 fetch 请求不顾一切的依赖缓存, 即使缓存过期了, 它依然从缓存中读取, 除非没有任何缓存, 那么它将发送一个正常的 request
- only-if-cached: 表示 fetch 请求不顾一切的依赖缓存, 即使缓存过期了, 它依然从缓存中读取. 如果没有缓存, 它将抛出网络错误( 该设置只是 mode为"same-origin"时有效 )
fetch 函数返回一个 Promise 对象
- 当收到服务器的返回结果后, Promise 进入 resolved 状态, 状态数据为 Response 对象
- 当网络发生错误( 或其他导致无法完成交互的错误 ) 时, Promise 进入 rejected 状态, 状态数据为错误信息
- ok : boolean, 当响应消息码在 200 ~ 299 之间时为 true, 其他为 false
- status: number, 响应的状态码
- text(): 用于处理文本格式 Ajax 响应. 它从响应中获取文本流, 将其读完, 然后返回一个被解决为 String对象的 Promise
- blob(): 用于处理二进制文件格式 (比如图片或电子表格) 的 Ajax 响应. 它读取文件的原始数据, 一旦读取完整个文件, 就返回一个对解决为 blob 对象的 Promise.
- json(): 用于处理 JSON 格式的 Ajax 的响应. 它将 JSON 数据流转换为一个被解决为 JavaScript 对象的 Promise.
- redirect(): 可以用于重定向到另一个 url. 它会创建一个新的 Promise, 以解决来自重定向的 URL 的响应.
4、fetch请求分3种格式
(1)本地目录文本格式
(2)本地目录json格式
(3)网络请求格式
5、基本的fetch请求
fetch('url地址')//第一个参数url是必须填的,
.then(function(res){
//res中存放的是response响应内容
//console.log(res.json())会打印一个promise对象
//response是只能被读取一次的,console.log取一次,return取一次,会报错
return res.json();//返回一个promise对象
// res.json() 返回的数据类型是json 格式
// res.text() 返回的是文本格式
// res.blob() 处理 二进制 主要针对 图片 以及 流
}).then(function(myJson){
console.log(myJson)//数据在此处打印出来
//前一个没有返回值则会显示undefined
})
执行第一个then方法中的return res.json();会返回一个新的Promise实例对象
执行第二个then方法会根据前面promise对象的状态发生变化来调用的
6、解释两次then用法:
第一次then用法:then是根据promise的状态变化而执行的回调函数,promise的状态变化由resolve()函数决定,then的参数为resolve函数传递出来的数据,直接输出res是一个对象不是我们需要的数据,使用res.json()或者res.test()获取到我们需要的数据。
res.json() / res.text() 获取到的是一个新的promise实例,arr.txt 的值在[[[PromiseResult]]里面,但是直接取是取不出来的。没有方法取出来,Promise的设计文档中说了,[[PromiseResult]]是个内部变量,外部无法得到,只能在then中获取。所以就会用到第二次then了。
第一个 then 的return返回值是一个promise实例对象,所以回调链转交给了新的实例对象,第二个then的回调函数参数为PromiseValue的值,当返回值不是对象,而是数据类型时,会将该返回值赋值给PromiseValue,供下次的then函数使用
7、fetch号称ajax替代品,使用了ES6中的Promise对象。
优点如下:语法简洁,基于标准 Promise 实现,支持 async/await
缺点如下:
(1)fetch只对网络请求报错,对400,500都当做成功的请求,需要封装去处理。
(2)fetch默认不会带cookie,需要添加配置项。
(3)fetch不支持abort(正在支持中),不支持超时控制,使用setTimeout及Promise.reject的实现的超时控制并不能阻止请求过程继续在后台运行,造成了流量的浪费。
(4)fetch没有办法原生监测请求的进度,而XHR可以。