axios二次封装解决了什么问题?(项目常用)
axios二次封装:就是把大部分接口公共的参数配置提取出来统一进行处理。
1、代码封装,重用性高,减少代码量,减低维护难度。
2、统一处理一些常规的问题一劳永逸,如http错误。
3、拦截请求和响应,提前对数据进行处理,如获取token,修改配置项。
Axios基础配置- 实践
1) 全局的 axios 默认值
- axios.defaults.baseURL = 'https://api.example.com';
- axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
- axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
2) 自定义实例默认值
- // 创建实例时设置配置的默认值
- var instance = axios.create({
- baseURL: 'https://api.example.com'
- });
- // 在实例已创建后修改默认值
- instance.defaults.headers.common['Authorization'] = AUTH_TOKEN;
3) 区分环境配置
- let env = "dev";
- switch (env) {
- case 'dev':
- axios.defaults.baseURL = "http://127.0.0.1:8888";
- break;
- case 'test':
- axios.defaults.baseURL = "http://114.27.34.1:8888";
- break;
- case 'pro':
- axios.defaults.baseURL = "http://api.zhufeng.cn";
- break;
- }
4) 数据格式配置
- axios.defaults.headers['Content-Type'] = 'application/x-www-form-urlencoded';
- // axios.defaults.headers.common['Content-Type'] = 'application/x-www-form-urlencoded';
- // axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
- axios.defaults.transformRequest = function (data, headers) {
- let ContentType = headers['Content-Type'] || headers.common['Content-Type'] || headers.post['Content-Type'] || 'application/json';
- if (ContentType === "application/json") {
- return JSON.stringify(data);
- }
- if (ContentType === "application/x-www-form-urlencoded") {
- return Qs.stringify(data);
- }
- return data;
- };
项目实践-数据格式
- service.interceptors.request.use(
- (config) => {
- // 开发环境引入包装api
- config.url = `${BASE_URL}${config.url}`;
- config.headers['Cache-Control'] = 'no-cache,no-store,must-revalidate,max-age=-1,private';
- // post请求并且需要将data以form data 形式传给后端 需要传一个formType为true boolean
- if (config.method === 'post' && config.formType === true) {
- config.headers['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
- config.data = qs.stringify(config.data);
- }
- return config;
- },
- (error) => {
- // Do something with request error
- Promise.reject(error);
- }
- );
5) 拦截器
- // 添加请求拦截器
- axios.interceptors.request.use(function (config) {
- // 在发送请求之前做些什么
- return config;
- }, function (error) {
- // 对请求错误做些什么
- return Promise.reject(error);
- });
- // 添加响应拦截器
- axios.interceptors.response.use(function (response) {
- // 对响应数据做点什么
- return response;
- }, function (error) {
- // 对响应错误做点什么
- return Promise.reject(error);
- });
6) 响应的错误处理封装
interceptor作用就是拦截,可以针对请求参数和响应结果进行拦截处理,一般在项目当中,主要针对接口常规报错、网络报错、系统超时、权限认证等做拦截处理。
- axios.interceptors.response.use(function (response) {
- // 把获取的响应主体信息返回
- return response.data;
- }, function (reason) {
- // 失败:网络、状态码(Axios失败)
- let response = reason.response;
- if (response) {
- // 状态码不是2开头的
- switch (response.status) {
- //400 参数
- //401/403 Token
- //404 地址
- //500/503 服务器
- }
- } else {
- // 网络 / (超时 / 中断请求 -> code: "ECONNABORTED") ...
- if (reason && reason.code === "ECONNABORTED") {}
- if (!navigator.onLine) {}
- }
- return reason;
- });
一般项目,这样就没问题了,一套公共的参数配置。剩下都是请求的时候单独再配置即可。
Axios配置- 原理与源码
1) HTTP 拦截器的设计与实现
对于大多数 SPA 应用程序来说, 通常会使用 token 进行用户的身份认证。这就要求在认证通过后,我们需要在每个请求上都携带认证信息。如果在考虑对响应进行统一处理的话,我们的 request 函数将变得越来越庞大,也越来越难维护。那么对于这个问题,Axios 为我们提供了解决方案 —— 拦截器。
Axios 是一个基于 Promise 的 HTTP 客户端,而 HTTP 协议是基于请求和响应:
所以 Axios 提供了请求拦截器和响应拦截器来分别处理请求和响应。
1) 请求拦截器:该类拦截器的作用是在请求发送前统一执行某些操作,比如在请求头中添加 token 字段。
2) 响应拦截器:该类拦截器的作用是在接收到服务器响应后统一执行某些操作,比如发现响应状态码为 401 时,自动跳转到登录页。
2) 二次封装配置代码:(参考)
- import axios from 'axios';
- import qs from 'qs';
- /*
- * 根据环境变量区分接口的默认地址
- */
- switch (process.env.NODE_ENV) {
- case "production":
- axios.defaults.baseURL = "http://api.zhufengpeixun.cn";
- break;
- case "test":
- axios.defaults.baseURL = "http://192.168.20.12:8080";
- break;
- default:
- axios.defaults.baseURL = "http://127.0.0.1:3000";
- }
- /*
- * 设置超时时间和跨域是否允许携带凭证
- */
- axios.defaults.timeout = 10000;
- axios.defaults.withCredentials = true;
- /*
- * 设置请求传递数据的格式(看服务器要求什么格式)
- * x-www-form-urlencoded
- */
- axios.defaults.headers['Content-Type'] = 'application/x-www-form-urlencoded';
- axios.defaults.transformRequest = data => qs.stringify(data);
- /*
- * 设置请求拦截器
- * 客户端发送请求 - > [请求拦截器] - > 服务器
- * TOKEN校验(JWT):接收服务器返回的token,存储到vuex/本地存储中,每一次向服务器发请求,我们应该把token带上
- */
- axios.interceptors.request.use(config => {
- // 携带上token
- let token = localStorage.getItem('token');
- token && (config.headers.Authorization = token);
- return config;
- }, error => {
- return Promise.reject(error);
- });
- /*
- * 响应拦截器
- * 服务器返回信息 -> [拦截的统一处理] -> 客户端JS获取到信息
- */
- axios.defaults.validateStatus = status => {
- // 自定义响应成功的HTTP状态码
- return /^(2|3)\d{2}$/.test(status);
- };
- axios.interceptors.response.use(response => {
- return response.data;
- }, error => {
- let {
- response
- } = error;
- if (response) {
- //=>服务器最起码返回结果了
- switch (response.status) {
- case 401: //=>权限
- break;
- case 403: //=>服务器拒绝执行(token过期)
- break;
- case 404: //=>找不到页面
- break;
- }
- } else {
- //=>服务器连结果都没有返回
- if (!window.navigator.onLine) {
- // 断网处理:可以跳转到断网页面
- return;
- }
- return Promise.reject(error);
- }
- });
- export default axios;
【编辑推荐】