[toc]
### Fetch Api概述
Fetch Api并非ES6语言标准范围内的内容,其属于HTML5新增的 Web Api,但由于其采用Promise方式,更利于异步代码的书写。因此将该方法放在异步处理后面进行学习。
**XMLHttpRequest的问题**
1. 所有的功能全部集中在同一个对象上,容易书写出混乱不易维护的代码
2. 采用传统的事件驱动模式,无法适配新的 Promise Api
**Fetch Api 的特点**
1. Fetch Api并非取代 AJAX,而是对 AJAX 传统 API 的改进
2. 精细的功能分割:头部信息、请求信息、响应信息等均分布到不同的对象,更利于处理各种复杂的 AJAX 场景
3. 使用 Promise Api,更利于异步代码的书写
4.
### Fetch Api的用法
#### 基本使用
> 请求测试地址:http://101.120.82.37:5200/testapi/local (仅为书写,该地址不可用)
使用 ```fetch``` 函数即可立即向服务器发送网络请求
```js
// fetch的标准用法
const url = "http://101.120.82.37:5200/testapi/local";
const resp = await fetch(url) //当服务器有响应,获得其返回结果的Promise对象
const result = await resp.json(); //将服务器返回的Promise对象中的返回结果以json格式返回
console.log(result)
```
#### 参数
该函数有两个参数:
1. 必填,字符串,请求地址
2. 选填,对象,请求配置
**请求配置对象**
- method:字符串,请求方法,默认值GET
- headers:对象,请求头信息
- body: 请求体的内容,必须匹配请求头中的 Content-Type
- mode:字符串,请求模式
- cors:默认值,配置为该值,会在请求头中加入 origin 和 referer
- no-cors:配置为该值,不会在请求头中加入 origin 和 referer,跨域的时候可能会出现问题
- same-origin:指示请求必须在同一个域中发生,如果请求其他域,则会报错
- credentials: 如何携带凭据(cookie)
- omit:默认值,不携带cookie
- same-origin:请求同源地址时携带cookie
- include:请求任何地址都携带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 状态,状态数据为错误信息
### Request 对象
除了使用基本的fetch添加参数的方法,还可以通过创建一个Request对象做为参数传给fetch来完成请求(实际上,fetch的内部也会把传递进来的参数创建成一个Request对象)
```js
new Request(url地址, 配置)
```
```js
//定义一个Request对象
function getRequest(){
let url = 'http://101.120.82.37:5200/testapi/local'
let req = new Request(url, {});
return req
}
//发送fetch请求的时候可以这样写
let resp = fetch(getRequest()); //得到请求返回的Promise对象
let result = resp.json(); //用json格式获得请求返回的结果
console.log(result);
```
**注意**
尽量保证每次请求都是一个新的Request对象。如果定义好了一个Request对象,重新发送请求的时候Request对象中的数据并没有改变,但又想得到一个新的Request对象,可以使用Request对象的clone方法。
```js
function getRequest(){
let url = 'http://101.120.82.37:5200/testapi/local'
let req = new Request(url, {});
return req.clone()
}
//这样每次就会获得一个新的Request对象
```
### Response 对象
Response对象是fetch发送请求后,Promise对象返回resolve结果时的对象。该对象通常为返回时自动创建。
该对象的基本属性如下:
- 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 的响应。
Response对象也可以手动创建,用于模拟服务器返回的数据。平时很少使用
```js
const resp = new Response(`[
{'id': 0, 'name': '小张'},
{'id': 1, 'name': '小刘'},
]`, //第一个参数用来写json格式的数据体,可以使用模版字符来创建
{
ok: true,
status: 200,
} //第二个参数用来设置Response对象中的相关属性
)
```
### Headers 对象
在Request和Response对象内部,会将传递的请求头对象,转换为一个Headers对象
开发过程中,通常请求头中的数据基本不变,可以声明一个Headers对象,省去每次发送请求时都要重复填写请求头内容。
```js
const header = new Headers({
title: '标题',
content: '内容'
})
//这样就创建了一个请求头对象,结合上面的Request对象,发送请求的时候参数可以直接填写两个对象名即可
const resp = fetch(getRequest(), header)
//这种方式可以更加的节省代码的重复书写
```
获取返回数据中的Headers对象:
```js
const result = resp.headers
```
Headers对象中的方法:
- has(key):检查请求头中是否存在指定的key值
- get(key): 得到请求头中对应的key值
- set(key, value):修改对应的键值对
- append(key, value):添加对应的键值对
- keys(): 得到所有的请求头键的集合
- values(): 得到所有的请求头中的值的集合
- entries(): 得到所有请求头中的键值对的集合
### 文件上传
流程:
1. 客户端将文件数据发送给服务器
2. 服务器保存上传的文件数据到服务器端
3. 服务器响应给客户端一个文件访问地址
> 测试地址:http://101.120.82.37:5200/testapi/local
> 键的名称(表单域名称):imagefile
请求方法:POST
请求的表单格式:multipart/form-data
请求体中必须包含一个键值对,键的名称是服务器要求的名称,值是文件数据
> HTML5中,JS仍然无法随意的获取文件数据,但是可以获取到input元素中,被用户选中的文件数据
> 可以利用HTML5提供的FormData构造函数来创建请求体