赞
踩
npm install axios
文档链接:中文文档
这里仅封装常用的 get、post、put、delete 几种方法
且只封装几种常见的报错提示
src/utils/request.ts
import axios, { AxiosError, AxiosInstance, AxiosResponse, InternalAxiosRequestConfig, } from "axios"; const config = { baseURL: "http://localhost:3000/api", timeout: 10000, withCredentials: true, headers: {}, }; class RequestHttp { service: AxiosInstance; constructor() { this.service = axios.create(config); /** * @description 请求拦截器 */ this.service.interceptors.request.use( (config: InternalAxiosRequestConfig) => { return config; } ); /** * @description 响应拦截器 */ this.service.interceptors.response.use( (response: AxiosResponse) => { const { data } = response; return data; }, (error: AxiosError) => { const { response } = error; if (response) { checkStatus(response.status); } return false; } ); } // 常用请求方法封装 get(url: string, params?: object, _object = {}) { return this.service.get(url, { params, ..._object }); } post(url: string, params?: object, _object = {}) { return this.service.post(url, params, _object); } put(url: string, params?: object, _object = {}) { return this.service.put(url, params, _object); } delete(url: string, params?: any, _object = {}) { return this.service.delete(url, { params, ..._object }); } } /** * @description: 校验网络请求状态码 * @param {Number} status * @return void */ const checkStatus = (status: number): void => { switch (status) { case 404: console.warn("资源不存在!"); break; case 405: console.warn("请求方式错误!"); break; case 500: console.warn("服务器异常!"); break; default: console.warn("请求失败!"); } }; const request = new RequestHttp(); export default request;
增加如下处理
src/utils/request.ts
import { message } from "antd"; import axios, { AxiosInstance, InternalAxiosRequestConfig, AxiosResponse, AxiosError, } from "axios"; import { store } from "@/redux"; import { ResponseCodeEnum } from "@/enums/httpEnum"; import { setToken } from "@/redux/modules/global"; import { ResultData } from "@/api/types/index.type"; import fullLoading from "./fullLoading"; import { AxiosCancel } from "./AxiosCancel"; const config = { baseURL: "http://localhost:3000/api", timeout: 5000, withCredentials: true, headers: {}, }; const axiosCancel = new AxiosCancel(); class RequestHttp { service: AxiosInstance; constructor() { this.service = axios.create(config); /** * @description 请求拦截器 */ this.service.interceptors.request.use( (config: InternalAxiosRequestConfig) => { console.log(config) // 打开全局 loading // 如不需要全局 loading,则第三个参数 { headers: { noLoading: true } } if(!config.headers.noLoading) { fullLoading.show(); } // 将请求添加到 pending 中 axiosCancel.addPending(config); // 这里如果需要添加token const token = store.getState().global.token; // 我这里用的是 react-redux + redux-toolkit config.headers["X-Access-Token"] = token; return config; } ); /** * @description 响应拦截器 */ this.service.interceptors.response.use( (response: AxiosResponse) => { const { data, config } = response; // 关闭全局 loading if(!config.headers.noLoading) { fullLoading.hide(); } // 请求结束,移除本次请求 axiosCancel.removePending(config.url, config.method); // 接口返回 code 不是 200 的处理 if (data.code !== ResponseCodeEnum.SUCCESS) { message.error(data.msg); // 登录失效,清除 token,跳转到登录页面 if (data.code === ResponseCodeEnum.NOLOGIN) { store.dispatch(setToken("")); window.location.href = "/login"; } return Promise.reject(data); } return data; }, (error: AxiosError) => { fullLoading.hide(); const { response } = error; if (response) { checkStatus(response.status); } return false; } ); } // 常用请求方法封装 get<T>(url: string, params?: object, _object = {}): Promise<ResultData<T>> { return this.service.get(url, { params, ..._object }); } post<T>(url: string, params?: object, _object = {}): Promise<ResultData<T>> { return this.service.post(url, params, _object); } put<T>(url: string, params?: object, _object = {}): Promise<ResultData<T>> { return this.service.put(url, params, _object); } delete<T>(url: string, params?: any, _object = {}): Promise<ResultData<T>> { return this.service.delete(url, { params, ..._object }); } } /** * @description: 校验网络请求状态码 * @param {Number} status * @return void */ const checkStatus = (status: number): void => { switch (status) { case 404: message.error("资源不存在!"); break; case 405: message.error("请求方式错误!"); break; case 500: message.error("服务器异常!"); break; default: message.error("请求失败!"); } }; const request = new RequestHttp(); export default request;
取消请求的封装:
src/utils/AxiosCancel.ts
import axios, { AxiosRequestConfig, Canceler } from "axios"; const cancelMap = new Map<string, Canceler>(); export class AxiosCancel { /** * 添加请求的 cancel * @param config */ addPending(config: AxiosRequestConfig) { const { url, method } = config; if (!url || !method) return; // 处理同个api,同时多次请求的情况,先移除上一个 this.removePending(url, method); const key = getCancelMapKey(url, method); config.cancelToken = new axios.CancelToken((cancel: Canceler) => { if (!cancelMap.has(key)) { cancelMap.set(key, cancel); } }); } /** * 移除请求 * @param url * @param method */ removePending(url: string | undefined, method: string | undefined) { if (!url || !method) return; const key = getCancelMapKey(url, method); const cancel = cancelMap.get(key); if (cancel) { cancel(); cancelMap.delete(key); } } /** * 移除所有请求 */ removeAllPending() { cancelMap.forEach((cancel) => { cancel && cancel(); }); cancelMap.clear(); } } function getCancelMapKey(url: string, method: string) { return `${url}_${method}`; }
全局加载loading
src/utils/fullLoading.ts
import ReactDOM from "react-dom/client"; import { Spin } from "antd"; // 当前请求的个数 let reqCount = 0; // 显示 loading function show() { if (reqCount === 0) { const dom = document.createElement("div"); dom.id = "loading"; dom.style.position = "fixed"; dom.style.top = "0"; dom.style.right = "0"; dom.style.bottom = "0"; dom.style.left = "0"; dom.style.background = "rgba(0, 0, 0, 0.5)"; dom.style.display = "flex"; dom.style.justifyContent = "center"; dom.style.alignItems = "center"; dom.style.zIndex = "9999"; document.body.appendChild(dom); ReactDOM.createRoot(dom).render(<Spin size="large"></Spin>); } reqCount++; } // 隐藏 loading function hide() { reqCount--; if (reqCount === 0) { const dom = document.getElementById("loading"); if (dom) { document.body.removeChild(dom as HTMLElement); } } } const fullLoading = { show, hide, }; export default fullLoading;
src/enums/httpEnum.ts
/**
* @description:响应结果枚举
*/
export enum ResponseCodeEnum {
SUCCESS = 200,
ERROR = 500,
NOLOGIN = 499,
}
类型文件
src/api/type/api.type.ts
// 接口返回结构,不包含 data
export interface ResponseResult {
// 状态码
code: number;
// 消息
msg: string;
}
// 完整的接口返回结构
export interface ResultData<T = any> extends ResponseResult {
// 数据
data: T;
}
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。