简介
Axios,是一个基于promise网络请求库,作用于node.js和浏览器中,它是 isomorphic 的(即同一套代码可以运行在浏览器和node.js中)。在服务端它使用原生node.js http模块, 而在客户端 (浏览端) 则使用XMLHttpRequests
参考资料
认识 axios
- Axios简单的理解就是ajax的封装
- Axios 是一个基于 promise 的 HTTP 库
- 支持node端和浏览器端
- 使用Promise管理异步,告别传统callback方式
- 丰富的配置项,支持拦截器等高级配置
- 转换请求数据和响应数据
接口案例
- 项目的两种编程方式:模板式编程(服务端渲染好的模板返回,例如 jsp)、接口式编程(现在基本都是这种,前后端分离)
- RestFul API 规范(URL,HTTP, 版本, 状态码, 返回值, 请求条件等规范)
- GET(SELECT):从服务器取出资源(一项或多项)。
- POST(CREATE):在服务器新建一个资源。
- PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。(更新表内一行的所有数据)
- PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)。(更新表内一行数据的一部分字段)
- DELETE(DELETE):从服务器删除资源。
- 我们配置接口时,这只是一种规范,只是
建议
大家按照规范来使用而已。
Promise
简介
- 主要用于异步计算
- 可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果
- 可以在对象之间传递和操作promise,帮助我们处理队列
- 异步回调的问题:
- 之前处理异步是通过纯粹的回调函数的形式进行处理
- 很容易进入到回调地狱中,剥夺了函数return的能力
- 问题可以解决,但是难以读懂,维护困难
- 稍有不慎就会踏入回调地狱 - 嵌套层次深,不好维护
- promise
- promise是一个对象,对象和函数的区别就是对象可以保存状态,函数不可以(闭包除外)
- 并未剥夺函数return的能力,因此无需层层传递callback,进行回调获取数据
- 代码风格,容易理解,便于维护
- 多个异步等待合并便于解决
状态
- Promise总共有三种状态:
pending
reslove
reject
- pending就是未决,resolve可以理解为成功,reject可以理解为拒绝
- pending 可能会转变为 resolve
- pending 也可能会转变为 reject
- then() 函数回调后如果函数中没有发生错误会返回一个 resolve 状态的 Promise,如果回调中发生错误会返回一个 reject 状态的 Promise 然后触发 catch 的函数,同理如果 catch 中的执行没有发生错误依旧也会返回一个 resolve 状态的 Promise,还是可以走后面的 then 回调
回调地狱
- 回调地狱简单说就是 套娃 请求A,但是A又依赖于B,因此在请求的A里面包含着B,同时B又依赖着C,因此B里面又包含着C,C又包含着D 这种模式就称为回调地狱
用法
异步
- 任何一个 then 中如果发生错误会走 catch 的回调,这里没有定义
- 每增加一个回调就按照这种格式写比前面的更加清晰
同步
- Promise.all 传递的参数是一个数组
- 多个任务完成后才会触发下一个回调
- 多个任务返回的也是一个数组
axios
简介
- axios 发起请求后返回的就是一个 Promise 对象,所以要先掌握 Promise
- 接口是本地 mock 的一些,主要看效果
示例一
- html 中通过 srcipt 引入 axios 方式进行测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.26.0/axios.min.js"></script> </head> <body> <script> axios("http://127.0.0.1:4523/mock/673120/getUser?id=1&author=ada") .then(res => console.log(res.data))
axios({ method: "get", url: "http://127.0.0.1:4523/mock/673120/getUser", params: {id: 1, author: "ada"} }) .then(res => console.log(res.data)) axios({ method: "POST", url: "http://127.0.0.1:4523/mock/673120/getInfo", headers: { "content-type": "application/json" }, data: { cid: 10000, region: "mock" } }) .then(res => console.log(res.data)) </script> </body> </html>
|
线上环境使用
安装依赖
- 上面是通过引入 js 文件方式,下面我们将通过安装 axios 依赖的方式直接使用
1 2 3 4 5 6
| npm i axios -S npm i webpack webpack-cli html-webpack-plugin -D
yarn add axios -S yarn add webpack webpack-cli html-webpack-plugin -D
|
文件及配置
- 根目录下新建 src/index.js 和 src/index.html 两个文件
- 根目录下新建 webpack.config.js 配置文件
- 配置 webpack
1 2 3 4 5 6 7 8
| const htmlWebpackPlugin = require("html-webpack-plugin"); module.exports = { mode: "development", entry: "./src/index.js", plugins: [ new htmlWebpackPlugin({template: "./src/index.html"}) ] }
|
基础语法
- index.js 的内容(新建了空的 index.html文件,webpack 打包后会引入这个 js )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import axios from "source/_posts/worker/Developer/Axios";
axios.get("http://127.0.0.1:4523/mock/673120/getUser?id=1&author=ada") .then(res => { console.log(res); })
axios.get("http://127.0.0.1:4523/mock/673120/getUser", {params: {id: 1}}) .then(res => { console.log(res); })
axios.post("http://127.0.0.1:4523/mock/673120/getInfo", "cid=10000®ion=mock") .then(res => { console.log(res); })
|
并发
- axios 的并发和 Promise的同步是一样的 axios.all Promise.all 请求参数都是一个数据,返回也是一个数据
- axios.spread 方法可以用参数分别接收每一个请求的结果,参数个数和发起的请求个数一致
- ajax请求过多对页面性能可能会有影响,以及代码不美观,代码过于臃肿,所以我们可以使用 axios的并发请求axios.all()
- axios.all() 这个方法在 axios 的构造函数是没有的,没在实例对象上。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| import axios from "source/_posts/worker/Developer/Axios";
axios.all([ axios.get("http://127.0.0.1:4523/mock/673120/getUser?id=1&author=ada"), axios.get("http://127.0.0.1:4523/mock/673120/getUser", {params: {id: 1}}), axios.post("http://127.0.0.1:4523/mock/673120/getInfo", "cid=10000®ion=mock") ]) .then(res => { console.log("--------------------all_res--------------------"); console.log(res); }) .catch(err => { console.log(err); })
axios.all([ axios.get("http://127.0.0.1:4523/mock/673120/getUser?id=1&author=ada"), axios.get("http://127.0.0.1:4523/mock/673120/getUser", {params: {id: 1}}), axios.post("http://127.0.0.1:4523/mock/673120/getInfo", "cid=10000®ion=mock") ]) .then(axios.spread((res1, res2, res3) => { console.log("--------------------res1 res2 res3--------------------"); console.log(res1); console.log(res2); console.log(res3); })) .catch(err => console.log(err))
|
全局环境配置
- axios.defaults 可配置全局环境,这里简单提取两个baseURL timeout 还有很多可扩展
- axios.default.headers.post[‘content-type’]=’application/x-www-form-urlencoded’;
- 整理数据
1 2 3 4 5
| # 整理数据 axios.defaults.transformRequest = function (data) { data = JSON.stringify(data); return data; };
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| axios.defaults.baseURL = "http://127.0.0.1:4523/mock/673120"; axios.defaults.timeout = 5000;
axios.get("getUser?id=123&author=ada") .then(res => { console.log(res); })
axios.post("getInfo", "cid=10000®ion=mock") .then(res => { console.log(res) }) .catch(err => { console.log(err); });
|
实例封装
简介
- 有时候后台接口地址有多个并且超时时长不一样,我们不可能在axios中把每个后台请求的域名地址都拼接在URl中,并且在axios中的config写不同的超时时长,很繁琐,这个时候可以用到axios实例,在实例中可以配置这两种参数。
- 如果新建了一个axios实例但是没有参数,取得就是全局的配置值,实例中如果有则优先取实例中的
- axios实例的相关配置(config参数)
- baseURL:请求的域名基本地址(如:http://localhost:8080)
- timeout:后端定义的超时时长(默认是1000ms)
- url:请求的路径(如:/data.json)
- method:请求方法(get、post…..)
- headers:设置请求头
- params:请求的参数拼接在url中
- data:请求的参数放在request body中
创建实例
- 如果同时定义了 axios.defaults 和实例中定义了同样的优先会用实例自己的
- 如果实例中没有定义会使用 axios.defaults 的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| let user = axios.create({ baseURL: "http://127.0.0.1:4523/mock/673120", timeout: 2000, });
let getUser = axios.create({ baseURL: "http://127.0.0.1:4523/mock/673120/getUser", timeout: 2000, method: "get", });
let info = axios.create({ baseURL: "http://127.0.0.1:4523/mock/673120", timeout: 3000,
})
user.get("getUser?id=111&author=ada") .then(res => { console.log(res) })
info.post("getInfo", "cid=10000®ion=mock") .then(res => { console.log(res) })
getUser({ params: {id: 123, author: "阿达"} }) .then(res => { console.log(res); })
|
拦截器
示例
- 拦截器分为请求拦截器 和响应拦截器
- 实际用途:①请求拦截器:比如为每个请求都带上的参数,比如token,时间戳等 ②响应拦截器:比如对返回的状态进行判断,如token是否过期
- 拦截器可以为整个 axios 设置,也可以针对具体的某个实例进行设置
- 在使用拦截器的时候 响应拦截器可以进行设置只放行状态为 200 的,并且只放行 data(我们只return data数据)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| import axios from "source/_posts/worker/Developer/Axios";
let getUser = axios.create({ baseURL: "http://127.0.0.1:4523/mock/673120/getUser", timeout: 2000, method: "get", });
let info = axios.create({ baseURL: "http://127.0.0.1:4523/mock/673120", timeout: 3000, })
info.interceptors.request.use(config => { console.log("info 请求拦截的配置和操作比如添加 token onFulfilled 状态"); return config; }, err => { console.log("info 请求拦截失败了会走下面这个代码块 onRejected 状态"); })
info.post("getInfo", "cid=10000®ion=mock") .then(res => { console.log(res) })
getUser.interceptors.response.use(config => { console.log("getUser onFulfilled 状态 响应拦截的配置和操作比如只放行状态码为 200 的 "); return config.data; }, err => { console.log("getUser 响应拦截失败了会走下面这个代码块 onRejected 状态"); }) getUser({ params: {id: 123, author: "阿达"} }) .then(res => { console.log(res); })
|
扩展
- 一些常用的配置 添加 token 和返回状态的设置(全局 axios 有效)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| axios.interceptors.request.use( config => { const token = window.localStorage.getItem("token"); token && (config.headers.Authorization = token); return config; }, error => { return Promise.error(error); } );
axios.interceptors.response.use( response => { if (response.status === 200) { return Promise.resolve(response); } else { return Promise.reject(response); } }, error => { if (error.response.status) { return Promise.reject(error.response); } } );
|