【JavaScript】axios 二次封装拦截器(接口、实例、全局)

news/2024/11/3 3:40:02 标签: javascript, 开发语言, ecmascript

学习 coderwhy 老师结合 ts 二次封装 axios

目录结构

在这里插入图片描述

config

config\index.ts

// export const BASE_URL = "http://codercba.com:9002";
export const TIME_OUT = 10000;

// 1. 根据环境变量区分接口地址
// let BASE_URL: string;
// if (process.env.NODE_ENV === "development") {
//   BASE_URL = "http://codercba.com:9002"
// } else {
//   BASE_URL = "http://codercba.com:9002"
// }

// 2. 通过创建 .env 文件来自定义环境变量
const BASE_URL  = process.env.REACT_APP_BASE_URL

export { BASE_URL }

request

request\index.ts

import axios, {AxiosInstance, InternalAxiosRequestConfig} from "axios";
import { RequestConfig } from "@/service/request/type";

class MyRequest {
  instance: AxiosInstance;

  constructor(config: RequestConfig) {
    this.instance = axios.create(config);

    // 1. 全局拦截器和实例拦截器
    this.instance.interceptors.request.use(
      function (config) {
        console.log("全局请求成功的拦截");
        return config;
      },
      function (error) {
        console.log("全局请求失败的拦截");
        return Promise.reject(error);
      }
    );

    this.instance.interceptors.response.use(
      function (response) {
        console.log("全局响应成功的拦截");
        return response.data;
      },
      function (error) {
        console.log("全局响应失败的拦截");
        return Promise.reject(error);
      }
    );

    // 2. 配置针对特殊的接口的单次请求拦截
    this.instance.interceptors.request.use(
      config.interceptors?.requestSuccessFn,
      config.interceptors?.requestFailureFn
    );
    this.instance.interceptors.response.use(
      config.interceptors?.responseSuccessFn,
      config.interceptors?.responseFailureFn
    );
  }

  /*
   * 我们希望对每次请求每个接口 request 和 response 都进行定制化的拦截
   * request({
   *   url:'/xxx',
   *   interceptors:{
   *     requestSuccessFn:(config) => {
   *       console.log("针对 /xxx 请求成功的拦截");
   *       return config;
   *     },
   *   }
   * })
   *
   * 某个接口的请求拦截 -> 全局请求拦截 -> 全局响应拦截 -> 某个接口的响应拦截
   * */

  /**
   * 封装请求方法
   * @param config
   */
  request<T = any>(config: RequestConfig<T>) {
    if (config.interceptors?.requestSuccessFn) {
      // 返回拦截处理后新的 config 
      // 如今新的源码里面需要使用 InternalAxiosRequestConfig 否则会报错
      config = config.interceptors.requestSuccessFn(config as InternalAxiosRequestConfig) as InternalAxiosRequestConfig;
    }
    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: RequestConfig<T>) {
    return this.request({ ...config, method: "GET" });
  }

  post<T = any>(config: RequestConfig<T>) {
    return this.request<T>({ ...config, method: "POST" });
  }

  delete<T = any>(config: RequestConfig<T>) {
    return this.request<T>({ ...config, method: "DELETE" });
  }

  patch<T = any>(config: RequestConfig<T>) {
    return this.request<T>({ ...config, method: "PATCH" });
  }
}

export default MyRequest;

request\type.ts

import {AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig} from "axios";

/**
 * 自定义拦截器类型
 */
export interface Interceptors<T = AxiosResponse> {
  requestSuccessFn?: (config: InternalAxiosRequestConfig) => InternalAxiosRequestConfig | Promise<InternalAxiosRequestConfig>;
  requestFailureFn?: (err: any) => any;
  responseSuccessFn?: (res: T) => T;
  responseFailureFn?: (err: any) => any;
}

/**
 * 针对于原有 axios 的配置进行二次封装(扩展)
 */
export interface RequestConfig<T = AxiosResponse> extends AxiosRequestConfig {
  interceptors?: Interceptors<T>;
}

index

index.ts

import {BASE_URL, TIME_OUT} from "@/service/config";
import MyRequest from "@/service/request";

export const request = new MyRequest({
  baseURL: BASE_URL,
  timeout: TIME_OUT
})

总结

  1. 配置的统一管理 .env 比如 timeout 和 baseUrl
  2. 拦截器二次封装(接口(通过 ts 类型约束和类的继承为每一个 request 方法添加自定义 interceptors 配置,配置上有请求和响应成功和失败的方法)、实例(类构造实例)、全局)
  3. 全局拦截(token 设置、loading 效果、message 弹窗提示)

整体下来最难的地方我感觉是 ts 类型的约束,不看一些源码真的理解不了。


http://www.niftyadmin.cn/n/5735945.html

相关文章

[HNCTF 2022 Week1]calc_jail_beginner_level3(JAIL)

开启靶场&#xff0c;打开链接&#xff0c;下载附件&#xff1a; 嗯&#xff0c;直接显示“Oh hacker!”&#xff0c;有点懵&#xff0c;先看看下载的附件&#xff08;server.py&#xff09;&#xff1a; 得到信息如下&#xff1a; 用户输入的表达式长度被限制在7个字符以内。…

Golang--DOS命令、变量、基本数据类型、标识符

1、DOS命令 切换盘符&#xff08;大小写没有区别&#xff09;&#xff1a; c: //切换到c盘 d: //切换到d盘 e: //切换到e盘 显示文件内信息&#xff1a; 指令&#xff1a;dir 切换路径&#xff1a; 指令&#xff1a;cd 绝对路径 / 相对路径 . 表示当前…

【Linux指令】---获取进程的PID

获取进程的PID getpid()函数

DB-GPT系列(二):DB-GPT部署(镜像一键部署、源码部署)

一、简介 DB-GPT 是一个开源项目&#xff0c;其将大语言模型 LLM 与数据库紧密结合。该项目主要致力于探索如何让预训练的大规模语言模型&#xff08;例如 GPT&#xff09;能够直接与数据库进行交互&#xff0c;从而生成更为准确且信息丰富的回答。 DB-GPT部署后能否直接使用…

GEE 教程——将图像剪切成多边形,并保留内部部分。 图像将保留所有原始波段

目录 简介 函数 unmask(value, sameFootprint) Arguments: Returns: Image selfMask() Arguments: Returns: Image 代码 结果 简介 将图像剪切成多边形,并保留内部部分。 图像将保留所有原始波段 函数 unmask(value, sameFootprint) Replaces mask and value of…

Android -- [SelfView] 自定义圆盘指针时钟

Android – [SelfView] 自定义圆盘指针时钟 ps:简约圆盘指针时钟&#xff0c;颜色可调、自由搭配&#xff1b;支持阿拉伯数字、罗马数字刻度显示&#xff1b;效果图 使用&#xff1a; <!-- 自定义属性参考 attrs.xml 文件 --> <com.nepalese.harinetest.player.Virg…

基于Spring Boot的大学城水电管理系统设计与实现

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的管理显得特别重要。因此&#xff0c;使用计算机来管理大学城水电管理系统的相关信息成为必然。开…

Java Collection/Executor LinkedTransferQueue 总结

前言 相关系列 《Java & Collection & 目录》《Java & Executor & 目录》《Java & Collection/Executor & LinkedTransferQueue & 源码》《Java & Collection/Executor & LinkedTransferQueue & 总结》《Java & Collection/Execu…