【Vue3+TypeScript】CRM系统项目搭建之 — Axiox 网络请求封装(一):https://developer.aliyun.com/article/1556820
六、axios拦截器
axios提供了两大类拦截器:
- 一种是请求方向的拦截(成功的、失败的)
- 一种是响应方向的拦截(成功的,失败的)
拦截器作用:
比如:请求之前在请求头加token、强制登录
响应的时候可以进行相应的数据处理
请求拦截器
//创建实例 let request = axios.create({ baseURL:'http://localhost:8080', timeout:5000 }); //配置axios拦截器 request.interceptors.request.use(config=>{ console.log("请求进来了...") console.log("请求成功方向") console.log(config.data.data) //放行请求,这一步很重要,否则报错 return config; },err=>{ console.log("请求进来了...") console.log("请求失败方向") console.log(err) }); //如果没有创建实例,则使用以下方式 //配置axios拦截器 // axios.interceptors.request.use(config=>{ // console.log("请求进来了...") // console.log("请求成功方向") // console.log(config) // //放行请求 // return config; // },err=>{ // console.log("请求进来了...") // console.log("请求失败方向") // console.log(err) // }); //使用实例 request({ url:'get/getAll' }).then(res=>{ console.log(res.data.data) });
响应拦截器
//创建实例 let request = axios.create({ baseURL:'http://localhost:8080', timeout:5000 }); //配置axios拦截器 request.interceptors.response.use(config=>{ console.log("响应进来了...") console.log("响应成功方向") console.log(config.data.data) //放行响应 return config; },err=>{ console.log("响应进来了...") console.log("响应失败方向") console.log(err) }); //使用实例 request({ url:'get/getAll' }).then(res=>{ console.log(res.data.data) });
七、vue 中封装 axios
封装在request.js中
//导入axios import axios from 'axios' //创建axios实例 const service = axios.create({ baseURL: process.env.VUE_APP_BASE_API, timeout: 5000 }) //请求拦截器 service.interceptors.request.use( config => { if (store.getters.token) { config.headers['token'] = getToken() } //放行请求 return config }, error => { console.log(error) return Promise.reject(error) } ) //响应拦截器 service.interceptors.response.use( response => { //返回的数据 const res = response.data if (res.code !== 200) { Message({ message: res.message || 'Error', type: 'error', duration: 5 * 1000 }) // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired; if (res.code === 50008 || res.code === 50012 || res.code === 50014) { // to re-login MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', { confirmButtonText: 'Re-Login', cancelButtonText: 'Cancel', type: 'warning' }).then(() => { store.dispatch('user/resetToken').then(() => { location.reload() }) }) } return Promise.reject(new Error(res.message || 'Error')) } else { return res } }, error => { console.log('err' + error) // for debug Message({ message: error.message, type: 'error', duration: 5 * 1000 }) return Promise.reject(error) } ) export default service
哪个模块需要发送请求直接引入即可,将以上实例导入
比如:此模块的所有请求接口:api下的skuInfo.js
//导入axios实例 const api_name = '/admin/product/skuInfo' export default { getPageList(page, limit, searchObj) { return request({ url: `${api_name}/${page}/${limit}`, method: 'get', params: searchObj }) }, save(role) { return request({ url: `${api_name}/save`, method: 'post', data: role }) }, //新人专享 isNewPerson(id, status) { return request({ url: `${api_name}/isNewPerson/${id}/${status}`, method: 'get' }) }, }
list.vue页面中使用
//先导入 import api from '@/api/product/skuInfo' api.getPageList(this.page, this.limit, this.searchObj).then( response => { debugger this.list = response.data.records this.total = response.data.total // 数据加载并绑定成功 this.listLoading = false } ) } api.save(this.skuInfo).then(response => { if (response.code) { this.$message({ type: 'success', message: response.message }) this.$router.push({ path: '/product/skuInfo/list' }) this.saveBtnDisabled = false } }) //新人专享 handleNewPersonChange(index, row) { api.isNewPerson(row.id, row.isNewPerson).then(response => { this.$message({ type: 'info', message: '操作成功' }) this.fetchData() }) } }
main.js中引入使用
import * as API from '@/api' Vue.prototype.$API = API
八、立足当前项目
service / index.ts
import { BASE_URL, TIME_OUT } from './config' import HYRequest from './request' const hyRequest = new HYRequest({ baseURL: BASE_URL, timeout: TIME_OUT }) export default hyRequest
service / config / index.ts
// 1.区分开发环境和生产环境 // export const BASE_URL = 'http://coderwhy.dev:8000' // export const BASE_URL = 'http://codercba.prod:8000' // 2.代码逻辑判断, 判断当前环境 // vite默认提供的环境变量 // console.log(import.meta.env.MODE) console.log(import.meta.env.DEV) // 是否开发环境 console.log(import.meta.env.PROD) // 是否生产环境 console.log(import.meta.env.SSR) // 是否是服务器端渲染(server side render) let BASE_URL = '' if (import.meta.env.PROD) { BASE_URL = 'http://codercba.prod:8000' } else { BASE_URL = 'http://coderwhy.dev:8000' } console.log(BASE_URL) // 3.通过创建.env文件直接创建变量 console.log(import.meta.env.VITE_URL) export const TIME_OUT = 10000 export { BASE_URL }
service / request / index.ts
import axios from 'axios' import type { AxiosInstance } from 'axios' import type { HYRequestConfig } from './type' // 拦截器: 蒙版Loading/token/修改配置 /** * 两个难点: * 1.拦截器进行精细控制 * > 全局拦截器 * > 实例拦截器 * > 单次请求拦截器 * 2.响应结果的类型处理(泛型) */ class HYRequest { instance: AxiosInstance // request实例 => axios的实例 constructor(config: HYRequestConfig) { this.instance = axios.create(config) // 每个instance实例都添加拦截器 this.instance.interceptors.request.use( (config) => { // loading/token return config }, (err) => { return err } ) this.instance.interceptors.response.use( (res) => { return res.data }, (err) => { return err } ) // 针对特定的hyRequest实例添加拦截器 this.instance.interceptors.request.use( config.interceptors?.requestSuccessFn, config.interceptors?.requestFailureFn ) this.instance.interceptors.response.use( config.interceptors?.responseSuccessFn, config.interceptors?.responseFailureFn ) } // 封装网络请求的方法 // T => IHomeData request<T = any>(config: HYRequestConfig<T>) { // 单次请求的成功拦截处理 if (config.interceptors?.requestSuccessFn) { config = config.interceptors.requestSuccessFn(config) } // 返回Promise return new Promise<T>((resolve, reject) => { this.instance .request<any, T>(config) .then((res) => { // 单词响应的成功拦截处理 if (config.interceptors?.responseSuccessFn) { res = config.interceptors.responseSuccessFn(res) } resolve(res) }) .catch((err) => { reject(err) }) }) } get<T = any>(config: HYRequestConfig<T>) { return this.request({ ...config, method: 'GET' }) } post<T = any>(config: HYRequestConfig<T>) { return this.request({ ...config, method: 'POST' }) } delete<T = any>(config: HYRequestConfig<T>) { return this.request({ ...config, method: 'DELETE' }) } patch<T = any>(config: HYRequestConfig<T>) { return this.request({ ...config, method: 'PATCH' }) } } export default HYRequest
service / request / type.ts
import type { AxiosRequestConfig, AxiosResponse } from 'axios' // 针对AxiosRequestConfig配置进行扩展 export interface HYInterceptors<T = AxiosResponse> { requestSuccessFn?: (config: AxiosRequestConfig) => AxiosRequestConfig requestFailureFn?: (err: any) => any responseSuccessFn?: (res: T) => T responseFailureFn?: (err: any) => any } export interface HYRequestConfig<T = AxiosResponse> extends AxiosRequestConfig { interceptors?: HYInterceptors<T> }