request.js配置
1.request.js
/** * 自定义 request 网络请求工具,基于axios */ import axios, { AxiosPromise, AxiosRequestConfig, AxiosResponse } from 'axios'; import { ElNotification } from 'element-plus'; import router from '@/routes'; import { getToken, setToken } from '@/utils/localToken'; // 可单独配置在 /config/settings 文件里 const settings = { ajaxResponseNoVerifyUrl: [ '/user/login', // 用户登录 '/user/info', // 获取用户信息 ], ajaxHeadersTokenKey: 'x-token' } export interface ResponseData { code: number; data?: any; msg?: string; token?: string; } const customCodeMessage: {[key: number]: string} = { 10002: '当前用户登入信息已失效,请重新登入再操作', // 未登陆 }; const serverCodeMessage: {[key: number]: string} = { 200: '服务器成功返回请求的数据', 400: 'Bad Request', 401: 'Unauthorized', 403: 'Forbidden', 404: 'Not Found', 500: '服务器发生错误,请检查服务器(Internal Server Error)', 502: '网关错误(Bad Gateway)', 503: '服务不可用,服务器暂时过载或维护(Service Unavailable)', 504: '网关超时(Gateway Timeout)', }; /** * 异常处理程序 */ const errorHandler = (error: any) => { const { response, message } = error; if (message === 'CustomError') { // 自定义错误 const { config, data } = response; const { url, baseURL} = config; const { code, msg } = data; const reqUrl = url.split("?")[0].replace(baseURL, ''); const noVerifyBool = settings.ajaxResponseNoVerifyUrl.includes(reqUrl); if (!noVerifyBool) { ElNotification({ type: 'error', title: `提示`, message: customCodeMessage[code] || msg || 'Error', }); if (code === 10002) { router.replace('/user/login'); } } } else if (message === 'CancelToken') { // 取消请求 Token // eslint-disable-next-line no-console } else if (response && response.status) { const errorText = serverCodeMessage[response.status] || response.statusText; const { status, request } = response; ElNotification({ type: 'error', title: `请求错误 ${status}: ${request.responseURL}`, message: errorText, }); } else if (!response) { ElNotification({ type: 'error', title: '网络异常', message: '您的网络发生异常,无法连接服务器', }); } return Promise.reject(error); } /** * 配置request请求时的默认参数 */ const request = axios.create({ baseURL: process.env.VUE_APP_APIHOST, // url = api url + request url withCredentials: true, // 当跨域请求时发送cookie timeout: 0 // 请求超时时间,5000(单位毫秒) / 0 不做限制 });
/** * 请求前 * 请求拦截器 */ request.interceptors.request.use( async (config: AxiosRequestConfig & { cType?: boolean }) => { // 如果设置了cType 说明是自定义 添加 Content-Type类型 为自定义post 做铺垫 if (config['cType']) { config.headers['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'; } // 自定义添加token header const headerToken = await getToken(); if (headerToken) { config.headers[settings.ajaxHeadersTokenKey] = headerToken; } return config; } ); /** * 请求后 * 响应拦截器 */ request.interceptors.response.use( async (response: AxiosResponse) => { const res: ResponseData = response.data; const { code, token } = res; // 自定义状态码验证 if (code !== 0) { return Promise.reject({ response, message: 'CustomError', }); } // 重置刷新token if (token) { await setToken(token); } return response; } ); export default function(config: AxiosRequestConfig): AxiosPromise<any> { return request(config).then((response: AxiosResponse) => response.data).catch(error => errorHandler(error)); }
2.localToken.js
/** * 自定义 token 操作 */ import localforage from 'localforage'; // 可单独配置在 /config/settings 文件里 const settinpgs = { siteTokenKey: 'admin_element_vue_token' } /** * 获取本地Token */ export const getToken = async (): Promise<string | null> => { return await localforage.getItem(settings.siteTokenKey); }; /** * 设置存储本地Token */ export const setToken = async (token: string): Promise<boolean> => { try { await localforage.setItem(settings.siteTokenKey, token); return true; } catch (error) { return false; } }; /** * 移除本地Token */ export const removeToken = async (): Promise<boolean> => { try { await localforage.removeItem(settings.siteTokenKey); return true; } catch (error) { return false; } };