fetch的基础语法
fetch是ES6新增加的一个api,以一种全新的方式去实现数据请求。
MDN文档-使用fetch
向服务器发送数据请求的方案:
第一类:XMLHttpRequest
+ ajax:自己编写请求的逻辑和步骤(四步:1.创建一个XMLHttpRequest实例 2.open 3.onReadyStateChange监听 4.send)
+ axios:第三方库,对XMLHttpRequest进行封装「基于promise进行封装」(有效管理异步编程)
第二类:fetch
ES6内置的API,本身就是基于promise,用全新的方案实现客户端和服务器端的数据请求
+ 不兼容IE
+ 机制的完善度上,还是不如XMLHttpRequest的「例如:无法设置超时时间、没有内置的请求中断的处理...」
第三类:其它方案,主要是跨域为主
+ jsonp
+ postMessage
+ 利用img的src发送请求,实现数据埋点和上报
+ ...
fetch基础语法:let promise实例(p) = fetch(请求地址,配置项);
- 当请求成功,p的状态是fulfilled,值是请求回来的内容;如果请求失败,p的状态是rejected,值是失败原因!
- fetch和axios有一个不一样的地方:
- 在fetch中,只要服务器有反馈信息(不论HTTP状态码是多少),都说明网络请求成功,最后的实例p都是fulfilled,只有服务器没有任何反馈(例如:请求中断、请求超时、断网等),实例p才是rejected!
- 在axios中,只有返回的状态码是以2开始的,才会让实例是成功态!
配置项:
- method 请求的方式,默认是GET「GET、HEAD、DELETE、OPTIONS;POST、PUT、PATCH;」
- cache 缓存模式「*default, no-cache, reload, force-cache, only-if-cached」
- credentials 资源凭证(例如cookie)「include, *same-origin, omit」(在客户端和服务器通信中,只要客户端设置了cookie,在每一次请求的时候,默认就会在请求头中,基于cookie字段,把本地设置的cookie信息,传递给服务器。)
fetch默认情况下,跨域请求中,是不允许携带资源凭证的,只有同源下才允许
include:同源和跨域下都可以
same-origin:只有同源才可以
omit:都不可以 - headers:普通对象{}/Headers实例
自定义请求头信息 - body:设置请求主体信息
- 只适用于POST系列请求,在GET系列请求中设置body会报错{让返回的实例变为失败态}
- body内容的格式是有要求的,并且需要指定 Content-Type 请求头信息
- JSON字符串 application/json
'{"name":"xxx","age":14,...}'
- URLENCODED字符串 application/x-www-form-urlencoded
'xxx=xxx&xxx=xxx'
- 普通字符串 text/plain
- FormData对象 multipart/form-data
主要运用在文件上传(或者表单提交)的操作中let fm=new FormData(); fm.append('file',文件); ...
- 二进制或者Buffer等格式
- …
- JSON字符串 application/json
- 我们发现,相比较于axios来讲,fetch没有对GET系列请求问号传参的信息做特殊的处理(axios中基于params设置问号参数信息),需要自己手动拼接到URL的末尾才可以
fetch实现获取任务:
其中,headers:普通对象{}/Headers实例
普通对象:
let p = fetch('/api/getTaskList', {
headers: {
'Content-Type':'application/json'
}
})
Headers类:头处理类「请求头或者响应头」
Headers.prototype
- append 新增头信息
- delete 删除头信息
- forEach 迭代获取所有头信息
- get 获取某一项的信息
- has 验证是否包含某一项
- …
let head = new Headers;
head.append('Content-Type', 'application/json');
head.append('name', '52lkk');
// head.forEach((key, value) => {
// console.log(value, key);
// })
let p = fetch('/api/getTaskList', {
headers: head
});
p.then(response => {
console.log('成功:', response);
}).catch(reason => {
console.log('失败:', reason);
});
服务器返回的response对象【Response类的实例】
私有属性:
- body 相应主体信息【它是一个ReadableStream可读流】
- headers 响应头信息【它是Headers类的实例】
- status/statusText 返回的HTTP状态码及描述
Response.prototype
- arrayBuffer
- blob
- formData
- json
- text
- …
这些方法就是用来处理body可读流信息的,把可读流信息转换为我们需要的格式。
转换后的返回值仍然是一个promise实例,原因: 这样可以避免服务器返回的信息在转换中出现问题(例如:服务器返回的是一个二进制文件流信息,我们转换为json对象肯定是不对的,此时让其返回失败的实例即可)
let p = fetch('/api/getTaskList', {
headers: head
})
p.then(response => {
//进入then中的时候,不一定是请求成功【因为状态码可能是各种情况】
let {
headers, status, statusText } = response
if (/^(2|3)\d{2}$/.test(status)) {
console.log('成功:', response);
//console.log('服务器时间:',headers.get('Date'));
return response.json()
}
//获取数据失败的【状态码不对】
return Promise.reject({
code: -100,
status,
statusText
})
}).then(value => {
console.log('最终处理后的结果: ', value);
}).catch(reason => {
//会有不同的失败情况
//1.服务器没有返回任何的信息
//2.状态码不对
//3.数据转换失败
//...
console.log('失败:', reason);
})
将请求地址改为一个不存在的地址,此时会返回404状态码,Promise rejected,走请求失败逻辑:
let p = fetch('/api/getTaskList', {
headers: head
})
此时:
将数据转换格式改为response.formatData(),人为使其数据格式转换失败,走失败逻辑:
if (/^(2|3)\d{
2}$/.test(status)) {
...
return response.formatData()
}
此时:
同理可以根据失败原因reason中的状态码code有无及status/statusText的不同做不同的错误原因提示。
fetch实现新增任务:
服务器要求urlencoded格式的信息,直接写一个普通对象不行,会把其变为一个object字符串传递给服务器,不符合服务器要求的信息格式,所以需要自己手动把请求主体格式变为服务器需要的===>
import qs from 'qs'
;同时手动设置请求头。
import qs from 'qs'
import {
message } from 'antd'
...
document.body.addEventListener('click', function () {
fetch(&