axios的封装 总有一个适合你

231 阅读5分钟

.env

开始之前vue管理系统中的axios的basUrlr如果不写一般会去找.env的文件 .env.company

  NODE_ENV = ''
  NODE_TYPE = ''
  ORG_NAME = ''
  ORG_CODE = ''
  VUE_APP_BASE_URL = 'ip地址'

.env.beijing

VUE_APP_BASE_URL = 'ip地址'

.env.company

VUE_APP_BASE_URL = 'ip地址'

axios.defaults

axios.defaults.baseURL = 是强制改变ip地址

方法一

如下,请求可以分为三部分
image.png

1.index.js中封装各类的请求,如get,post,put,delete,upload,login,logout,refresh等等请求。 2.request.js是创建一个axios赋予基础参数,并且添加响应拦截器。
3.requestUrl.js是用来抽取一个基础的url参数,并且做一个拼接。

下面按照这三个文件的引用顺序做一个单个文件的代码拆分分析

requestUrl.js

/**
 * 请求地址统一处理/组装
 * @param {*} actionName action方法名称
 */
export default function(actionName) {
    let url = process.env.VUE_APP_BASE_URL || "http://***.com"
    
    return url + actionName
}

request.js

/* jshint esversion: 6  */
import axios from "axios";
import Vue from "vue";
import router from "../router/index";
import store from "../store";
import requestUrl from "./requestUrl";

// 创建axios实例
const request = axios.create({
	timeout: 10000 * 10,
});

// response拦截器
request.interceptors.response.use(
	(response) => {
		// 101 用户名或密码错误
		// 102 REFRESH-TOKEN不存在/失效
		// 103 token验证失败
		// 104 未登录

		let code = response.data.code;
		if(code == 102 || (!store.state.refreshing && code == 104)){
			// 退出登陆
			store.commit("logout");
			router.replace({ name: "login" });
		}
		if (!store.state.refreshing && code == 103) {
			// token失效 刷新token
			Vue.prototype.ajax.refresh();
			response.data.msg = "长时间页面未更新,尝试重新提交或刷新页面";
		}
		return response.data;
	},
	(error) => {
		return Promise.reject(error);
	}
);
export { request, requestUrl };
复制代码

index.js

1.里面需要引入的模块如下

import { request, requestUrl } from "./request";
import store from "../store/index";
import Vue from "vue";
import qs from "qs";
复制代码

需要一个公共axios请求方法

/**
 * axios请求封装
 * @param {*} opt
 */
function send(opt, resolve, reject, success, error, complete) {
	// 获取refresh_token时,延迟请求
	if (store.state.refreshing) {
		setTimeout(() => {
			send(opt, resolve, reject, success, error, complete);
		}, 300);
		return;
	}
	let nowtime = new Date().getTime() / 1000;
        //overtime是登录成功之后端返回的时间加上登录的时间戳
	let overtime = Number(store.state.overtime);
	
	// 如果登陆时间大于8小时则直接退出
	if (store.state.token && overtime && nowtime - overtime > 8 * 3600) {
		store.commit("logout");
		router.replace({ name: "login" });
		return;
	}
	// 如果登陆时间小于8小时并且超出refreshtoken时间,则刷新token
	if (store.state.token && overtime && overtime < nowtime) {
		store.commit("changeRefresh", false);//改变store.state.refreshComplate
		ajax.refresh(opt, resolve, reject, success, error, complete);
		return;
	}
	if (store.state.refreshComplate) {
		let token = store.state.token;
		if (token) {
			opt.headers.token = token;
		}
	}
	request(opt)
		.then((res) => {
			resolve(res);
			if (success) success(res);
		})
		.catch((err) => {
			reject(err);
			if (error) error();
			Vue.prototype.$message.error("网络错误,请稍后重试");
		})
		.finally(() => {
			if (complete) complete();
		});
}

3.需要封装一个拿取token的方法

function getToken() {
	let token = store.state.token;
	if (!token) {
		store.commit("logout");
		Vue.prototype.$message.error("登陆信息失效,请重新登陆");
		router.replace({ name: "login" });
	}
	return token;
}
```js

## 4.定义一个ajax对象在里面封装各种类型的方法,并且导出它

```js
const ajax = {
    get(){},
    post(){},
    put(){},
    delete(){},
    upload(){},
    login(){},
    logout(){},
    refresh(){},
};
export { ajax };

get方法的封装

const ajax = {
	get: (url, params) => {
		let token = getToken();
		if (!token) return;
		let opt = {
			url: requestUrl(url),
			method: "get",
			headers: {
				"Content-Type": "application/x-www-form-urlencoded",
				token,
			},
			params,
		};
		return new Promise((resolve, reject) => {
			send(opt, resolve, reject);
		});
	}
}

post方法的封装

const ajax = {
        post: (url, params) => {
		let token = getToken();
		if (!token) return;
		let opt = {
			url: requestUrl(url),
			method: "post",
			headers: {
				"Content-Type": "application/x-www-form-urlencoded",
				token,
			},
			data: qs.stringify(params),
		};
		return new Promise((resolve, reject) => {
			send(opt, resolve, reject);
		});
	},
}

put方法的封装

const ajax = {
        put: (url, params) => {
		let token = getToken();
		if (!token) return;
		let opt = {
			url: requestUrl(url),
			method: "put",
			headers: {
				"Content-Type": "application/x-www-form-urlencoded",
				token,
			},
			data: qs.stringify(params),
		};
		return new Promise((resolve, reject) => {
			send(opt, resolve, reject);
		});
	},
}

delete方法的封装

const ajax = {
        delete: (url, params) => {
		let token = getToken();
		if (!token) return;
		let opt = {
			url: requestUrl(url),
			method: "delete",
			headers: {
				"Content-Type": "application/x-www-form-urlencoded",
				token,
			},
			params,
		};
		return new Promise((resolve, reject) => {
			send(opt, resolve, reject);
		});
	},
}
复制代码

upload方法的封装

const ajax = {
        upload: (url, params) => {
		let token = getToken();
		if (!token) return;
		let opt = {
			url: requestUrl(url),
			method: "post",
			headers: {
				"Content-Type": "multipart/form-data",
				token,
			},
			data: toFormData(params),
		};
		return new Promise((resolve, reject) => {
			send(opt, resolve, reject);
		});
	},
}

login方法的封装

const ajax = {
        login: (params) => {
		store.commit("isRefresh", false);
		let opt = {
			url: requestUrl("/login"),
			method: "post",
			headers: {
				"Content-Type": "application/x-www-form-urlencoded",
			},
			data: qs.stringify(params),
		};
		return new Promise((resolve, reject) => {
			send(opt, resolve, reject);
		});
	},
}

logout方法的封装

const ajax = {
        logout: () => {
		store.commit("isRefresh", false);
		let token = getToken();
		if (!token) return;
		let opt = {
			url: requestUrl("/logout"),
			method: "post",
			headers: {
				"Content-Type": "application/x-www-form-urlencoded",
				token,
			},
		};
		return new Promise((resolve, reject) => {
			send(opt, resolve, reject, false, false, () => {
				store.commit("logout");
			});
		});
	},
}
复制代码

refresh方法的封装

const ajax = {
        refresh: (...success) => {
		if (store.state.refreshing) return;
		store.commit("isRefresh", true);

		let opt = {
			url: requestUrl("/refresh_token"),
			method: "post",
			headers: {
				"Content-Type": "application/x-www-form-urlencoded",
				"refresh-token": store.state.refresh_token,
			},
		};
		return new Promise((resolve, reject) => {
			request(opt)
				.then((res) => {
					resolve(res);
					if (res.code == 0) {
						store.commit("setUserInfo", res.data);
						if (success) {
							if (success[0].headers && success[0].headers.token) {
								success[0].headers.token = res.data.token;
							}
							send(...success);
						}
					}else{
						ajax.logout()
					}
				})
				.catch((err) => {
					reject();
					Vue.prototype.$message.error("网络错误,请稍后重试");
				})
				.finally(() => {
					store.commit("isRefresh", false);
				});
		});
	},
}

使用 this.ajax.post(url, query)

方法二 挂载在window就可直接使用

// console.log(BASE, "配置文件config/api配置文件");
const HTTTPS = axios.create({
    baseURL: BASE.base ? BASE.base : window.location.origin ,
    timeout: 10000
})
HTTTPS.interceptors.request.use(config => {
    Loading({ type: 1, tipLabel: "加载中..." })
    config['Content-Type'] = 'application/x-www-form-urlencoded'
    return config
}, error => {
    return Promise.reject(error)
})
HTTTPS.interceptors.response.use(response => {
    // console.log(response,"response");
    switch (response.data.code) {
        case -1:
            console.log('网络连接未响应');
            break;
        case 416:
            sessionStorage.removeItem('userObj')
            sessionStorage.removeItem('TOKEN')
            sessionStorage.removeItem('RANDOMTOKEN')
            sessionStorage.removeItem('access_token')
            // window.location.href = "../index.html"
            break;
        default:
            break;
    }
    return response
}, error => {
    // 捕捉错误
    return Promise.reject(error)
})
console.log(HTTTPS.defaults,"HTTTPS");

const ajax = {
    get(url, query, gather) {
        return HTTTPS({
            method: 'get',
            url: url,
            headers: {
                'CONFERENCE-AUTH-TOKEN': gather ? gather.isToken ? sessionStorage.getItem('TOKEN') : '' : '',
                'CONFERENCE-AUTH-RANDOM': gather ? gather.isToken ? sessionStorage.getItem('RANDOMTOKEN') : '' : '',
            },
            params: query
        }).catch(e => {
            // HTTTPS.defaults.baseURL = WAIBASE.base
            // return this.get(url, query, gather)
        })
    },
    post(url, body, gather) {
        return HTTTPS({
            method: 'post',
            url,
            headers: {
                'CONFERENCE-AUTH-TOKEN': gather ? gather.isToken ? sessionStorage.getItem('TOKEN') : '' : '',
                'CONFERENCE-AUTH-RANDOM': gather ? gather.isToken ? sessionStorage.getItem('RANDOMTOKEN') : '' : '',
            },
            params: Qs.parse(body)
        }).catch(e => {
            // HTTTPS.defaults.baseURL = WAIBASE.base
            // return this.post(url, query, gather)
        })
    }
}
window['$http'] = ajax

使用: window['$http'].post(CONFIGURL['ROLEDEL'], { roleId: roleId }, gather = { isToken: true })

方法三

request.js

import axios from 'axios'
// 使用element-ui Message做消息提醒
import { Message} from 'element-ui';
//1. 创建新的axios实例,

const service = axios.create({
  //  baseURL:"http://tj139617.asuscomm.com:8201",
  baseURL:'https://api.aigou.store/api',
  // 超时时间 单位是ms
  timeout: 5 * 1000
})
// 2.请求拦截器
service.interceptors.request.use(config => {
   config.data = JSON.stringify(config.data); 
   config.headers = {
    'Content-Type':'application/json;charset=utf-8', //配置请求头
    // 'XX-Api-Version':'1.0',
    // 'XX-Device-Type':'pc'
  }
  const tokenHead = sessionStorage.getItem('tokenHead')
   const token =sessionStorage.getItem('token');//这里取token之前,需要先拿到token,存一下
   if(token){
      config.headers['Authorization']= tokenHead+token; //如果要求携带在请求头中
    }
  return config
}, error => {
  Promise.reject(error)
})
// 3.响应拦截器
service.interceptors.response.use(response => {
  return response
}, error => {
   /***** 接收到异常响应的处理开始 *****/
  if (error && error.response) {
    // 1.公共错误处理
    // 2.根据响应码具体处理
    switch (error.response.code) {
      case 400:
        error.message = '错误请求'
        break;
      case 401:
        error.message = '未授权,请重新登录'
        break;
      case 403:
        error.message = '拒绝访问'
        break;
      case 404:
        error.message = '请求错误,未找到该资源'
        window.location.href = "/NotFound"
        break;
      case 405:
        error.message = '请求方法未允许'
        break;
      case 408:
        error.message = '请求超时'
        break;
      case 500:
        error.message = '服务器端出错'
        break;
      case 501:
        error.message = '网络未实现'
        break;
      case 502:
        error.message = '网络错误'
        break;
      case 503:
        error.message = '服务不可用'
        break;
      case 10001:
        error.message = '网络超时'
        break;
      case 505:
        error.message = 'http版本不支持该请求'
        break;
      default:
        error.message = `连接错误${error.response.status}`
    }
  } else {
    // 超时处理
    if (JSON.stringify(error).includes('timeout')) {
      Message.error('服务器响应超时,请刷新当前页')
    }
    error.message = '连接服务器失败'
  }

  Message.error(error.message)
  /***** 处理结束 *****/
  //如果不需要错误处理,以上的处理过程都可省略
  return Promise.resolve(error.response)
})
//4.导入文件
export default service

http.js 引入request

import request from './request'

const http ={
    /**
     * methods: 请求
     * @param url 请求地址 
     * @param params 请求参数
     */
    get(url,params){
        const config = {
            method: 'get',
            url:url
        }
        if(params) config.params = params
        return request(config)
    },
    post(url,params){
        const config = {
            method: 'post',
            url:url
        }
        if(params) config.data = params
        return request(config)
    },
    put(url,params){
        const config = {
            method: 'put',
            url:url
        }
        if(params) config.params = params
        return request(config)
    },
    delete(url,params){
        const config = {
            method: 'delete',
            url:url
        }
        if(params) config.params = params
        return request(config)
    }
}
//导出
export default http

某个模块创建方法

import http from '../utils/http';
// 申请入驻列表
export function temporaryList(params){
    return http.get(`/mall-admin/shop/temporaryList`,params)
  }
  // 店铺统计
  export function getshopList(params){
    return http.get(`/mall-admin/statistics/shopList`,params)
  }

test.vue

import { temporaryList } from "@/api/cations.js";
let res = await temporaryList(params);

方法四

request.js

import axios from "axios";
import Vue from "vue";
import $store from "../store";
import $router from "../router";

// 判断当前的运行环境 process.env.NODE_ENV
// isDev 为真 开发环境 --- npm run serve
// isDev 为假 非开发环境(测试环境,生产环境)- npm run build
// const isDev = process.env.NODE_ENV === 'development'

let errorCount = 0;
let errorTimer = null;
const request = axios.create({
	baseURL: process.env.VUE_APP_BASE_URL,
});

// 请求拦截器 - 所有的请求开始之前先到此处
request.interceptors.request.use(
	(config) => {
		return config;
	},
	(error) => {
		return Promise.reject(error);
	}
);

// 响应拦截器 --- 所有请求的相应先到此处
request.interceptors.response.use(
	(response) => {
		// console.log(response.data.data)
		// 可以设置 加载的动画效果 的隐藏
		if (response.data.code == "10001" && $store.state.token) {
			Vue.prototype.ajax.logout();
			localStorage.removeItem("login");
			$store.commit("logout");

			Vue.prototype.$message({ message: "登陆失效,请重新登陆" });
			setTimeout(() => {
				$router.replace({ path: "/" });
			}, 1000);
		}
		return response.data;
	},
	(error) => {
		if (!errorTimer) {
			Vue.prototype.$message("链接服务器失败,请查看网络环境或配置文件");
      errorTimer = setTimeout(()=>{
        clearTimeout(errorTimer)
        errorTimer = null;
        errorCount = 0;
      },15000)
		}
		errorCount++;
		if (errorCount > 3 || $store.state.token) {
			Vue.prototype.ajax.logout();
			localStorage.removeItem("login");
			$store.commit("logout");
			setTimeout(() => {
				$router.replace({ path: "/" });
				errorCount = 0;
			}, 1000);
		}
		return Promise.reject(error);
	}
);
export default request;

ajax.js

import request from "./request";
import $store from "@/store/index";
import qs from "qs";

const ajax = {
  setBase: (url) => {
    request.defaults.baseURL = url
  },
  getBase: () => {
    return request.defaults.baseURL
  },
  get: (url, params) => {
    return request({
      url,
      method: "get",
      headers: {
        "XX-Api-Version": "1.0",
        "XX-Device-Type": $store.state.device,
        "XX-Token": $store.state.token || ""
      },
      params
    })
  },
  post: (url, params,isQs) => {
    return request({
      url,
      method: "post",
      headers: {
        "Content-Type": "application/x-www-form-urlencoded",
        "XX-Api-Version": "1.0",
        "XX-Device-Type": $store.state.device,
        "XX-Token": $store.state.token || ""
      },
      data:isQs ? params : qs.stringify(params)
    })
  },
  login: (params) => {
    return request({
      url: "/login",
      method: "post",
      headers: {
        "Content-Type": "application/x-www-form-urlencoded",
        "XX-Api-Version": "1.0",
        "XX-Device-Type": $store.state.device,
        "XX-Token": ""
      },
      data: qs.stringify(params)
    })
  },
  logout: () => {
    return request({
      url: "/logout",
      method: "get",
      headers: {
        "XX-Api-Version": "1.0",
        "XX-Device-Type": $store.state.device,
        "XX-Token": $store.state.token || ""
      }
    })
  },
  other: (url) => {
    return request({
      baseURL: url,
      method: "get",
      headers: {
        "XX-Api-Version": "1.0",
        "XX-Device-Type": $store.state.device,
        "XX-Token": $store.state.token || ""
      }
    })
  },
  // 上传
  uploadList:(params) =>{
    return request({
      url:'/upload',
      method:"post",
      headers:{
        "XX-Api-Version": "1.0",
        "XX-Device-Type": $store.state.device,
        "XX-Token": $store.state.token || ""
      },
      data: params
    })
  },
  // 分类管理 - 列表
  category:() =>{
    return request({
      url:"/admin/question/category",
      method:"get",
      headers:{
        "XX-Api-Version":"1.0",
        "XX-Device-Type":$store.state.device,
        "XX-Token":$store.state.token
      }
    })
  },
  
}


export default ajax;

main.js

import ajax from './api/ajax'
Vue.prototype.ajax = ajax;