当前位置: 首页 > news >正文

前端抽象化,打破框架枷锁:Http请求也许该一样

前言

个人博客原文地址

此文章并不适合初级前端来看,它是抽象的架构设计,需要一定的TS基础和抽象思维,若带着思考的读完本文章相信会让你感到充实

当然你也可以复制,然后在自己项目中去实现它,然后用起来

发送请求的库,和方法,有几种常用的,axios、fetch、uni.request等
通常我们会在一个文件中,写入大量长得几乎一模一样的函数,只是参数稍微改变,来储存大量请求函数
但是一旦使用的库变化了,这些或多或少,会有微调,如今我们将其抽象出来,让我们使用变统一,让其实现解耦合,达到更高的复用性和可维护性。

内容核心

  1. 请求参数与响应数据
    规定好参数和数据的格式,是整个系统的基础。将这部分提出来,让它们独立于具体实现。这样,你就能在不同的请求库中保持一致性,避免重复造轮子。

  2. 核心业务逻辑
    请求方法的核心逻辑是最重要的部分。它负责处理请求和响应,确保数据的正确性和完整性。同时请求的拦截器是最常用的功能,同样直接在这里抽象出来,以确定最重要的功能。

  3. 责任链
    另外的就是一个责任链设计,为了在拦截器中加入多个独立的功能,避免在请求方法中加入大量的逻辑判断,避免💩山代码。

  4. 插件
    而插件,则是要去实现责任链,让每个插件都使用责任链模式来链接,这样就能在请求方法中,轻松地添加、删除或修改插件,而不需要改动核心逻辑。你可以根据需要自由组合插件,形成不同的请求方式。比如,你可以有一个插件专门处理错误,一个插件专门处理缓存,还有一个插件专门处理重试等。这样,你就能根据实际需求灵活调整请求的行为,而不需要修改核心代码。

不过,这个插件的部分我写了三个示例,实际你可以自己来定义都有什么

  1. 适配器
    适配器很适合这种实现不同的情况,比如你需要在不同的环境中使用不同的请求库,或者你需要在不同的请求库中使用相同的请求方式。适配器可以帮助你实现这些需求,让你的代码更加灵活和可扩展。当然你也可以采用工厂模式,工厂模式能让你获得更多自由度,适配器模式则是可以更简单,而且通常来说一个项目,只会使用一个请求库,所以适配器模式更适合这种情况。

宏观的整体依赖关系

在这里插入图片描述

涉及的设计模式

  • 责任链模式:通过责任链模式,请求和响应的处理可以动态组合多个插件,增强扩展性和灵活性
  • 适配器模式:通过适配器模式,可以在不同的请求库之间切换,而不需要修改核心逻辑代码

设计的TS抽象源码

这里是一个设计的抽象模型,你可以根据这个模型去实现你的路由导航系统。无视框架,甚至无视语言,只要你能实现这个模型,你就可以在任何地方使用这个请求系统。
其他平台不是ts语言怎么办?AI会出手,助你转译

如果你不想先看这些源码,而是想看看图像👇

// DTO
/**
 * HTTP 请求方法枚举
 */
export const enum RequestMethod {
    GET = "GET",
    POST = "POST",
    PUT = "PUT",
    DELETE = "DELETE",
    PATCH = "PATCH"
}

/**
 * 请求参数接口
 */
export interface RequestParams<T = any> {
    /** 请求的 URL */
    url: string;
    /** 请求方法 */
    method: RequestMethod;
    /** 请求头 */
    headers?: Map<string, string>;
    /** 请求体数据(可选) */
    data?: T;
    /** 查询参数(可选) */
    params?: Map<string, string>;
    /** 元信息(可选) */
    meta?: Map<string, any>;
}

/**
 * 响应数据接口
 */
export interface ResponseData<T = any> {
    /** 响应状态码 */
    status: number;
    /** 响应消息 */
    message: string;
    /** 响应数据 */
    data: T;
    /** 元信息(可选) */
    meta?: Map<string, any>;
}

// Core
import { RequestParams } from "./DTO";
import { ResponseData } from "./DTO";

/**
 * 请求方法接口
 */
export interface IRequestMethod {
    /**
     * 发起 HTTP 请求
     * @param params 请求参数
     * @returns 响应数据
     */
    <P,R>(params: RequestParams<P>): Promise<ResponseData<R>>;
}

/**
 * 请求拦截器接口
 */
export interface IRequestInterceptor {
    /**
     * 请求前的拦截处理
     * @param params 请求参数
     * @param options 可选配置
     * @returns 修改后的请求参数
     */
    beforeRequest(params: RequestParams, options?: any): Promise<RequestParams>;
}

/**
 * 响应拦截器接口
 */
export interface IResponseInterceptor {
    /**
     * 响应前的拦截处理
     * @param response 响应数据
     * @returns 修改后的响应数据
     */
    beforeResponse(response: ResponseData): Promise<ResponseData>;
}

/**
 * 责任链抽象类
 */
export abstract class DutyChain {
    /** 下一个责任链节点 */
    private nextDutyChain: DutyChain | null = null;

    /**
     * 设置下一个责任链节点
     * @param handler 下一个责任链节点
     * @returns 当前责任链节点
     */
    public setNext(handler: DutyChain): DutyChain {
        this.nextDutyChain = handler;
        return handler;
    }

    abstract  canUse(params: RequestParams | ResponseData): boolean
    /**
     * 执行责任链处理
     */
    abstract handler(): Promise<void>

    /**
     * 处理逻辑(抽象方法)
     * @param params 请求或响应参数
     */
    protected abstract process(params: RequestParams | ResponseData): Promise<void>;
}

// plugins
import { DutyChain } from "./Core";
import { RequestParams } from "./DTO";
import { ResponseData } from "./DTO";

/**
 * 重复请求插件
 */
export class RepeatRequest extends DutyChain {
    canUse(params: RequestParams | ResponseData): boolean {
        throw new Error("Method not implemented.");
    }
    /**
     * 处理重复请求逻辑
     * @param params 请求参数
     */
    protected async process(params: RequestParams): Promise<void> {
        // 实现重复请求逻辑
    }

    /**
     * 执行责任链处理
     */
    public async handler(): Promise<void> {

    }
}

/**
 * 请求认证插件
 */
export class RequestAuth extends DutyChain {
    canUse(params: RequestParams | ResponseData): boolean {
        throw new Error("Method not implemented.");
    }
    /**
     * 处理请求认证逻辑
     * @param params 请求参数
     */
    protected async process(params: RequestParams): Promise<void> {
        // 实现请求认证逻辑
    }

    /**
     * 执行责任链处理
     */
    public async handler(): Promise<void> {

    }
}

/**
 * 消息处理插件
 */
export class Message extends DutyChain {
    canUse(params: RequestParams | ResponseData): boolean {
        throw new Error("Method not implemented.");
    }
    /**
     * 处理消息逻辑
     * @param response 响应数据
     */
    protected async process(response: ResponseData): Promise<void> {
        // 实现消息处理逻辑
    }

    /**
     * 执行责任链处理
     */
    public async handler(): Promise<void> {

    }
}

//FrameworkAdapters
import { IRequestMethod } from "./Core";
import { IRequestInterceptor } from "./Core";
import { IResponseInterceptor } from "./Core";
import { DutyChain } from "./Core";

/**
 * 抽象请求适配器类
 */
export abstract class AbstractRequestAdapter {
    /** 请求方法实例 */
    public request: IRequestMethod;
    /** 请求拦截器实例 */
    private requestInterceptor: IRequestInterceptor;
    /** 响应拦截器实例 */
    private responseInterceptor: IResponseInterceptor;
    /** 请求责任链 */
    public requestDutyChain: DutyChain;
    /** 响应责任链 */
    public responseDutyChain: DutyChain;
    /** 错误责任链 */
    public errorDutyChain: DutyChain;

    /**
     * 初始化方法
     */
    public abstract init(): void;
}

//Application
import { AbstractRequestAdapter } from "./FrameworkAdapters";

/**
 * 异步操作基类
 */
export abstract class AsyncBase {
    /** 请求适配器实例 */
    public Requester: AbstractRequestAdapter;

    /**
     * 构造函数
     * @param Requester 请求适配器实例
     */
    constructor(Requester: AbstractRequestAdapter) {
        this.Requester = Requester;
    }
}


// Demo
import { AsyncBase } from "../Application";
import { RequestMethod } from "../DTO";

export class Login extends AsyncBase {
  request = this.Requester.request;
  login(data: any) {
    return this.request<string,Record<string,any>>({
      url: "/login",
      method: RequestMethod.POST,
      data
    });
  }
}

图像也许会帮你更好的理解

流程图

在这里插入图片描述

类图

以下uml图,可以帮你快速的理解我这里的依赖关系,他是单向的,高层策略和低层策略是很明显的。

你可以右键下面这个图,在新的标签页中打开,这样可以放大和拖动的查看

这部分源码,我放到了github中,请去那边看吧👆
在这里插入图片描述

相关文章:

  • 数字化转型国家标准- GB/T 45341-2025《数字化转型管理 参考架构》
  • ThreadLocal 深度解析
  • 解决Certificate verification failed错误
  • linux--0.Linux的特点
  • 群体智能优化算法-变色龙优化算法(Chameleon Swarm Algorithm, CSA,含Matlab源代码)
  • cJSON 处理 JSON(轻量级 C 语言库)(二)
  • 蓝桥杯备赛:动态规划入门
  • 架构设计基础系列:面向对象设计的原则
  • 【Spring Boot 与 Spring Cloud 深度 Mape 之三】服务注册与发现:Nacos 核心实战与原理浅析
  • 【Easylive】服务端操作 Cookie 的完整流程(结合案例解析)
  • APIPost接口测试完整流程指南
  • java学习笔记11——泛型
  • 【Unity】 HTFramework框架(六十四)SaveDataRuntime运行时保存组件参数、预制体
  • Python WebSockets 库详解:从基础到实战
  • MySQL 5.7 Online DDL 技术深度解析
  • C++和C#接口对应关系
  • 【运维】Centos硬盘满导致开机时处于加载状态无法开机解决办法
  • Docker基础详解
  • Linux 高级路由策略控制配置:两个不同路由子网间通信
  • 沉浸式体验测评|AI Ville:我在Web3小镇“生活”了一周
  • 中铁城市发展投资集团原党委书记、董事长黄天德被查
  • 演员辛柏青发讣告:妻子朱媛媛患癌去世
  • 上海婚登人聂晶:见证爱情故事开启,也向长久婚姻致敬
  • 金融监管总局将研究出台专门的城市更新项目贷款管理办法:引导大力支持城中村的改造等
  • 研究显示:肺活量衰减始于20至25岁
  • 交通运输局男子与两名女子办婚礼?官方通报:未登记结婚,开除该男子