展望の概要:
ts は axios と統合 API を単純にカプセル化します
背景
axios の多くの追加機能はインターセプターに基づいて実装されています。一部の関数はグローバルに使用する必要があるため、インターセプターはグローバルに登録されます。たとえば、重複リクエストのフィルタリングなどです。ただし、ファイルの同時アップロードなど、フィルタリングしたくないリクエストも少数あります。
したがって、特定のリクエスト メソッドを構成することで、現在のリクエストに対して特定のインターセプターが有効になっているかどうかを判断できることを期待しています。
- デフォルトでは、構成項目は書き込まれず、有効になっている true としてマークされません。
- 構成項目が明示的に false に指定されている場合のみオフになります。
注: 特定のメソッドを構成する場合、それが明示的に true に構成されていないと、機能が有効にならない可能性があります。この関数は、インスタンス化中に構成オブジェクトで false に設定される可能性があるためです。この機能が axios インスタンス全体でオフになっている場合、有効にする前に、特定のメソッドを明示的に true に設定して、インスタンス化された構成を上書きする必要があります。
例として、現在のリクエストに対して応答フィードバックがオンになっているかどうかを確認します。
// index.ts
import HttpRequest from "./http/request";
// 实例化 axios
const httpRequest = new HttpRequest({
baseURL: import.meta.env.VITE_APP_API_BASE_URL,
timeout: import.meta.env.VITE_APP_API_TIMEOUT,
// 开启响应反馈拦截器功能(注册拦截器后,默认就是开启)
showMessage: true
});
// 在该 axios 实例上注册请求响应反馈拦截器
httpRequest.getInstance().interceptors.response.use(responseMessageOnFulfilled, null);
// 默认开启当前请求的请求响应弹窗反馈
async function handleMessageOpen() {
const res = await httpRequest.get({
url: "/mock/test"
});
console.log("res", res);
}
// 手动关闭当前请求的响应反馈
async function handleMessageClose() {
const res = await httpRequest.get({
url: "/mock/test",
showMessage: false
});
console.log("res", res);
}
拡張構成タイプ
axios config オブジェクトに追加の設定項目を追加するには、まずそのタイプを展開する必要がありますAxiosRequestConfig
。
// 开关的默认值(默认都是开启)
const DEFAULT_EXTRA_FEATURE_CONFIG = {
showMessage: true };
/** 扩展 axios 的请求配置类型 */
export interface MyAxiosRequestConfig<TReqBodyData = any> extends AxiosRequestConfig<TReqBodyData> {
showMessage?: boolean; // 是否开启请求反馈提示框
}
config オブジェクトはインターセプターでも必要です。しかし、最新の axios では、リクエスト インターセプターの config のタイプは ではなくなりましたAxiosRequestConfig
。InternalAxiosRequestConfig
したがって、リクエスト インターセプター構成InternalAxiosRequestConfig
タイプも拡張する必要があります。
/** 给拦截器使用 */
export interface MyInternalAxiosRequestConfig extends InternalAxiosRequestConfig {
showMessage?: boolean;
}
一部の関数は応答インターセプターの onFulfilled コールバックで完了します (フィードバックへの応答など)。また、一部の関数は onRejected コールバックで完了します (リクエストの再試行など)。AxiosResponse
したがって、応答インターセプター内のコールバックとAxiosError
その中の構成オブジェクト タイプを拡張することも必要です。
export interface MyAxiosResponse extends AxiosResponse {
config: MyInternalAxiosRequestConfig;
}
export interface MyAxiosError extends AxiosError {
config: MyInternalAxiosRequestConfig;
}
追加の構成項目を応答インターセプターに挿入する
さまざまな機能を実装するインターセプターは、リクエスト インターセプターまたはレスポンス インターセプターの場合があります。特定のメソッド設定に記入された設定項目は、リクエスト インターセプターで簡単に取得できます。ただし、AxiosResponse インスタンスの構成オブジェクトは新しく生成され、追加の構成項目がないため、応答インターセプターを取得するのは簡単ではありません。
したがって、ユーザーがリクエスト インターセプターに入力した構成アイテムの値を手動で保存し、それをレスポンス インターセプターの構成オブジェクトに手動で追加する必要があります。また、応答インターセプターは、最初に実行される応答インターセプターである必要があります。
class HttpRequest {
private readonly instance: AxiosInstance;
private readonly extraConfig: Record<string, boolean> = DEFAULT_EXTRA_FEATURE_CONFIG;
constructor(config: MyAxiosRequestConfig) {
this.instance = axios.create(config);
// 记录 config 额外配置项
this.instance.interceptors.request.use((config: MyInternalAxiosRequestConfig) => {
Object.keys(this.extraConfig).forEach(item => {
if (config[item as keyof MyInternalAxiosRequestConfig] === false)
this.extraConfig[item] = !!config[item as keyof MyInternalAxiosRequestConfig];
});
return config;
});
// 将配置项补充到响应的 config 对象上
this.instance.interceptors.response.use(
(res: any) => {
Object.keys(this.extraConfig).forEach(item => {
res.config[item] = this.extraConfig[item];
this.extraConfig[item] = true; // 配置复原成默认开启
});
return res;
},
(err: any) => {
Object.keys(this.extraConfig).forEach(item => {
err.config[item] = this.extraConfig[item];
this.extraConfig[item] = true; // 配置复原成默认开启
});
throw err;
}
);
}
...
}
リクエスト・レスポンス・フィードバック・インターセプタ
// src\api\http\message.ts
import {
MyAxiosResponse } from "./request";
// 假设接口:{code: number, data: any, msg: string}
function showMessage(res: MyAxiosResponse) {
const {
data } = res;
// alert 消息提示
if (data.code >= 200 && data.code < 300) alert(data.msg);
return res;
}
/**
* 响应业务消息提示
*/
export function responseMessageOnFulfilled(res: MyAxiosResponse) {
if (res.config.showMessage) showMessage(res); // showMessage 为 true,才给出反馈
return res;
}
使用例
<template>
<div>
<button @click="handleMessageOpen">message消息提示开</button>
<button @click="handleMessageClose">message消息提示关</button>
</div>
</template>
<script setup lang="ts">
import HttpRequest from "./http/request";
import { responseMessageOnFulfilled } from "./http/message";
// 实例化
const httpRequest = new HttpRequest({
baseURL: "/",
timeout: 10000
});
// 注册拦截器
httpRequest.getInstance().interceptors.response.use(responseMessageOnFulfilled);
// 反馈默认开
async function handleMessageOpen() {
const res = await httpRequest.get({
url: "/__api/mock/get_test"
// showMessage: true
});
console.log("res", res);
}
// 手动关闭反馈
async function handleMessageClose() {
const res = await httpRequest.get({
url: "/__api/mock/get_test",
showMessage: false
});
console.log("res", res);
}
</script>
結果:
要約する
特定のリクエストに対してインターセプターをオンにするという目的は、構成オブジェクトに追加の構成を追加することで達成されます。
- 拡張構成タイプ
- 追加の構成アイテムをリクエスト構成から応答構成オブジェクトに保存します。
- 特定の関数のインターセプターを作成する