React 中基于 Axios 的二次封装(含请求守卫)

张开发
2026/6/16 22:22:55 15 分钟阅读
React 中基于 Axios 的二次封装(含请求守卫)
React 中基于 Axios 的二次封装含请求守卫下面是一个完整的 Axios 二次封装方案包含 GET、POST 等方法的封装并加入了请求守卫拦截器功能。1. 基础封装 (axiosInstance.js)importaxiosfromaxios;import{message}fromantd;// 使用 Ant Design 的 message 作为示例可替换为其他 UI 库或自定义// 创建 axios 实例constaxiosInstanceaxios.create({baseURL:process.env.REACT_APP_API_BASE_URL||/api,// 基础路径timeout:10000,// 请求超时时间withCredentials:true,// 跨域请求时是否需要使用凭证});// 请求拦截器axiosInstance.interceptors.request.use((config){// 在发送请求之前做些什么// 例如添加 tokenconsttokenlocalStorage.getItem(token);if(token){config.headers.AuthorizationBearer${token};}// 可以在这里添加全局请求参数或修改 config// config.params { ...config.params, lang: zh-CN };returnconfig;},(error){// 对请求错误做些什么console.error(请求拦截器错误:,error);returnPromise.reject(error);});// 响应拦截器axiosInstance.interceptors.response.use((response){// 对响应数据做点什么// 假设后端返回的数据结构为 { code: 200, data: {}, message: }constresresponse.data;if(res.code200){returnres.data;// 直接返回数据部分}else{// 处理业务错误message.error(res.message||请求错误);returnPromise.reject(newError(res.message||Error));}},(error){// 对响应错误做点什么console.error(响应拦截器错误:,error);if(error.response){// 根据 HTTP 状态码处理不同错误switch(error.response.status){case401:message.error(未授权请登录);// 这里可以跳转到登录页// window.location.href /login;break;case403:message.error(拒绝访问);break;case404:message.error(请求的资源不存在);break;case500:message.error(服务器错误);break;default:message.error(error.response.data.message||请求失败);}}elseif(error.message.includes(timeout)){message.error(请求超时);}else{message.error(网络错误);}returnPromise.reject(error);});exportdefaultaxiosInstance;2. 请求方法封装 (request.js)importaxiosInstancefrom./axiosInstance;/** * 封装 GET 请求 * param {string} url 请求地址 * param {object} params 请求参数 * param {object} config 额外配置 * returns Promise */exportfunctionget(url,params{},config{}){returnaxiosInstance.get(url,{params,...config});}/** * 封装 POST 请求 * param {string} url 请求地址 * param {object} data 请求体数据 * param {object} config 额外配置 * returns Promise */exportfunctionpost(url,data{},config{}){returnaxiosInstance.post(url,data,config);}/** * 封装 PUT 请求 * param {string} url 请求地址 * param {object} data 请求体数据 * param {object} config 额外配置 * returns Promise */exportfunctionput(url,data{},config{}){returnaxiosInstance.put(url,data,config);}/** * 封装 DELETE 请求 * param {string} url 请求地址 * param {object} params 请求参数 * param {object} config 额外配置 * returns Promise */exportfunctiondel(url,params{},config{}){returnaxiosInstance.delete(url,{params,...config});}/** * 封装上传请求 * param {string} url 请求地址 * param {FormData} formData 表单数据 * param {object} config 额外配置 * returns Promise */exportfunctionupload(url,formData,config{}){returnaxiosInstance.post(url,formData,{headers:{Content-Type:multipart/form-data,},...config,});}// 可以继续添加其他封装方法...3. 使用示例importReact,{useEffect,useState}fromreact;import{get,post}from./request;functionUserList(){const[users,setUsers]useState([]);const[loading,setLoading]useState(false);const[error,setError]useState(null);useEffect((){constfetchUsersasync(){setLoading(true);try{constdataawaitget(/users);setUsers(data);}catch(err){setError(err.message);}finally{setLoading(false);}};fetchUsers();},[]);consthandleAddUserasync(){try{constnewUser{name:New User,age:25};constdataawaitpost(/users,newUser);console.log(添加成功:,data);// 可以刷新列表或做其他操作}catch(err){console.error(添加失败:,err);}};if(loading)returndiv加载中.../div;if(error)returndiv错误:{error}/div;return(divbutton onClick{handleAddUser}添加用户/buttonul{users.map(user(li key{user.id}{user.name}/li))}/ul/div);}exportdefaultUserList;4. 高级功能扩展4.1 请求取消功能// 在 axiosInstance.js 中添加constCancelTokenaxios.CancelToken;constsourceMapnewMap();// 用于存储请求的取消函数// 修改请求拦截器axiosInstance.interceptors.request.use((config){// 如果已有相同请求在执行则取消之前的请求constrequestKey${config.method}-${config.url};if(sourceMap.has(requestKey)){constcancelsourceMap.get(requestKey);cancel(取消重复请求);}// 创建新的取消令牌constsourceCancelToken.source();config.cancelTokensource.token;sourceMap.set(requestKey,source.cancel);returnconfig;},(error){returnPromise.reject(error);});// 修改响应拦截器axiosInstance.interceptors.response.use((response){// 请求成功后从 map 中移除对应的取消函数constconfigresponse.config;constrequestKey${config.method}-${config.url};sourceMap.delete(requestKey);returnresponse;},(error){if(axios.isCancel(error)){console.log(请求已取消:,error.message);}// 其他错误处理...returnPromise.reject(error);});// 导出取消请求的方法exportfunctioncancelRequest(method,url){constrequestKey${method}-${url};if(sourceMap.has(requestKey)){constcancelsourceMap.get(requestKey);cancel(主动取消请求);sourceMap.delete(requestKey);}}4.2 请求重试机制// 在 axiosInstance.js 中添加constretryCount2;// 重试次数constretryDelay1000;// 重试延迟时间(ms)// 修改请求拦截器或单独封装一个重试函数asyncfunctionretryRequest(config,retryNumretryCount){try{constresponseawaitaxiosInstance(config);returnresponse;}catch(error){if(retryNum0){throwerror;}console.log(请求失败重试${retryNum}次...);awaitnewPromise(resolvesetTimeout(resolve,retryDelay));returnretryRequest(config,retryNum-1);}}// 然后在需要的地方使用 retryRequest 代替直接调用 axiosInstance5. TypeScript 版本如果需要 TypeScript 版本可以这样修改// axiosInstance.tsimportaxios,{AxiosInstance,AxiosRequestConfig,AxiosResponse,AxiosError}fromaxios;interfaceResponseDataTany{code:number;data:T;message:string;}constaxiosInstance:AxiosInstanceaxios.create({baseURL:process.env.REACT_APP_API_BASE_URL||/api,timeout:10000,withCredentials:true,});axiosInstance.interceptors.request.use((config:AxiosRequestConfig){consttokenlocalStorage.getItem(token);if(token){config.headers!.AuthorizationBearer${token};}returnconfig;},(error:AxiosError){returnPromise.reject(error);});axiosInstance.interceptors.response.use((response:AxiosResponseResponseData){constresresponse.data;if(res.code200){returnres.data;}else{returnPromise.reject(newError(res.message||Error));}},(error:AxiosError){// 错误处理...returnPromise.reject(error);});exportdefaultaxiosInstance;// request.tsimportaxiosInstancefrom./axiosInstance;exportfunctiongetTany(url:string,params?:any,config?:AxiosRequestConfig):PromiseT{returnaxiosInstance.get(url,{params,...config});}exportfunctionpostTany(url:string,data?:any,config?:AxiosRequestConfig):PromiseT{returnaxiosInstance.post(url,data,config);}// 其他方法...这个封装方案提供了基础请求方法的封装请求和响应拦截器守卫错误统一处理可扩展的高级功能请求取消、重试等TypeScript 支持可选你可以根据实际项目需求进行调整和扩展。

更多文章