1、安装
文档链接:中文文档
2、常用封装
2.1 简单版本的封装
这里仅封装常用的 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;
复制代码 2.1 包罗多处置惩罚的封装
增加如下处置惩罚
- 哀求loading
- 取消哀求(CancelToken)
- 哀求效果的更细节处置惩罚
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;
- }
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |