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

经验总结:typescript 和 axios 项目中大量接口该如何管理和组织

引言

本文旨在介绍一种方法,用于在 typescript 和 axios 的项目中,有效的组合和管理大量的 API 接口以及 interface。

假如我们根据 API 文档对所有的接口做了初步分类,大体如下:

scm(某业务模块)
 ├── inventory(库存业务)
 │    ├── warehouse # 仓库资源
 │    ├── material  # 物料资源
 │    ├── unit      # 计量单位资源
 │    └── ...
 ├── order(订单业务)
 │     ├── order    # 订单资源
 │     ├── customer # 客户资源
 │     └── ...
 └── ...

具体来说,对于单个但资源后端提供了一系列 CRUD 操作接口, 以warehouse为例:

类型方法&路径
列表<GET /api/scm/warehouse/>
创建<POST /api/scm/warehouse/>
详情<GET /api/scm/warehouse/1/>
整体更新<PUT /api/scm/warehouse/1/>
部分更新<PATCH /api/scm/warehouse/1/>
删除<DELETE /api/scm/warehouse/1/>

在项目中,我们会有大量的资源,每种资源又会产生很多接口,对接这些接口我们需要创建很多请求函数,因此如何管理这些请求函数变得尤为重要。本文将介绍一种高效的组织方法,话不多说,让我们开始吧。

一、封装 axios

我们不讨论对axios的深度封装,这里只做最简单的处理:

// utils/request.ts
import { useTokenStore } from "@/stores/auth/token";
import axios from "axios";

// 后端API统一的返回结构
export type Result<T> = {
  status: string;
  code: number;
  message: string[];
  result: T;
};

const tokenStore = useTokenStore();
const access = tokenStore.getToken.access;

// 配置新建一个 axios 实例
const instance = axios.create({
  baseURL: import.meta.env.VITE_API_URL || "http://localhost:8000",
  timeout: 60000,
});

// 添加请求拦截器
instance.interceptors.request.use(
  function (config) {
    // 添加token
    if (access) {
      config.headers.Authorization = `Bearer ${access}`;
    }
    return config;
  },
  function (error) {
    // 对请求错误做些什么
    return Promise.reject(error);
  }
);

// 添加响应拦截器
instance.interceptors.response.use(
  function (response) {
    // 2xx 范围内的状态码都会触发该函数。
    // 对响应数据做点什么
    return response;
  },
  function (error) {
    // 超出 2xx 范围的状态码都会触发该函数。
    // 对响应错误做点什么
    return Promise.reject(error);
  }
);

export default instance;

二、对接接口

在引言中我们介绍了所有的资源接口,以及其分类:

scm(某业务模块)
 ├── inventory(库存业务)
 │    ├── warehouse # 仓库资源
 │    ├── material  # 物料资源
 │    ├── unit      # 计量单位资源
 │    └── ...
 ├── order(订单业务)
 │     ├── order    # 订单资源
 │     ├── customer # 客户资源
 │     └── ...
 └── ...

根据分类,我们创建下面的目录接口来存放请求函数:

/vue-project
├── /src
│   └── /api
│        ├── ...
│        └── /scm
│            ├── inventory.ts  (示例所在)
│            ├── order.ts
│            ├── ...
│            └── index.ts

warehouse资源为例,我们要为其所有的资源操作接口创建请求方法、要为其所有接口的请求体和响应体创建interface

// .../scm/inventory.ts
import request, { type Result } from "@/utils/request";

const baseUrl = "/api/scm";

// 仓库接口
// ----------------------------------------------------
export interface WarehouseBaseIn {
  name: string;
  code: string;
}

export interface WarehouseBaseOut {
  id: number;
  name: string;
  code: string;
  created_by: number;
  created_at: string;
}

export interface WarehousePatchIn {
  name?: string;
  code?: string;
}

export const warehouse = {
  list: () =>
    // 获取列表
    request<Result<WarehouseBaseOut[]>>({
      url: baseUrl + "/warehouse/",
      method: "GET",
    }),
  create: (data: WarehouseBaseIn) =>
    // 创建
    request<Result<WarehouseBaseOut[]>>({
      url: baseUrl + "/warehouse/",
      method: "POST",
      data,
    }),
  retrieve: (id: string) =>
    // 按ID查询
    request<Result<WarehouseBaseOut[]>>({
      url: baseUrl + `/warehouse/${id}/`,
      method: "GET",
    }),
  put: (id: string, data: WarehouseBaseIn) =>
    // 全部更新
    request<Result<WarehouseBaseOut[]>>({
      url: baseUrl + `/warehouse/${id}/`,
      method: "PUT",
      data,
    }),
  patch: (id: string, data: WarehousePatchIn) =>
    // 部分更新
    request<Result<WarehouseBaseOut[]>>({
      url: baseUrl + `/warehouse/${id}/`,
      method: "PATCH",
      data,
    }),
  destroy: (id: string) =>
    // 删除
    request<Result<any>>({
      url: baseUrl + `/warehouse/${id}/`,
      method: "Delete",
    }),
};

// 除了warehouse之外,inventory文件中实际上还会有更多的接口。
// 比如: material、unit等等,封装的方法都是类似的。
// ...

对单个资源的封装可以总结为如下结构:

const source = {
    list: function...,
    create: function...,
    retrieve: function...,
    put: function...,
    patch: function...,
    destroy: function...
}

回顾我们的目录结构:

/vue-project
├── /src
│   └── /api
│        ├── ...
│        └── /scm
│            ├── inventory.ts   (示例所在)
│            ├── order.ts
│            ├── ...
│            └── index.ts

上述的目录结构,使得我们可以对大量的资源进行分类组织,而为了方便请求函数调用,我们还需要在index.ts中对请求函数进行汇总。

// .../scm/index.ts
import { warehouse, material, unit,... } from './inventory'
import { order, customer, ... } from './order'

const api = {
  inventory: {
    warehouse,
    material,
    unit,
    ...
  },
  order: {
    order,
    customer,
    ...
  }
}

export default api

使用方法如下,并且能够充分得到 ide 提示:

import api from "@/api/scm";

// 使用.时ide的提示会很友好
api.inventory.warehouse.list();
api.inventory.material.list();
api.order.customer.list();
api.order.order.list();

总结

对资源接口做好分类,将请求函数组织在合理的目录结构中,有助于提高代码的可维护性和可扩展性。同时对请求函数进行统一封装和组织,使得对请求的调用更加方便。


http://www.kler.cn/a/371560.html

相关文章:

  • 字符串-05-字符串合并处理
  • 开源项目-投票管理系统
  • OpenHarmony4.0配置应用开机自启
  • Vue中使用 vuedraggable进行拖拽
  • 如何将原本打开Edge呈现出的360浏览器,更换成原本的Edge页面或者百度等其他页面
  • 基于 ThinkPHP+Mysql 灵活用工_灵活用工系统_灵活用工平台
  • 牛客算法简单题(JS版)
  • R语言在机器学习中的应用
  • unity中的材质(material)贴图(texture)着色器(shader)介绍
  • C++设计模式创建型模式———生成器模式
  • 【jvm】什么是TLAB
  • Ubuntu 22.04系统启动时自动运行ROS2节点
  • 【机器学习】Softmax 函数
  • GraphQL系列 - 第1讲 GraphQL语法入门
  • 计算机毕业设计——ssm基于HTML5的互动游戏新闻网站的设计与实现录像演示2021
  • R_机器学习——常用函数方法汇总
  • Java进阶篇设计模式之四 -----适配器模式和桥接模式
  • 会议录音转文字怎么转?有这6款视频语音转文字工具就够了!
  • 微信小程序时间弹窗——年月日时分
  • G2 基于生成对抗网络(GAN)人脸图像生成
  • Pytorch学习--神经网络--非线性激活
  • 【Unity基础】初识UI Toolkit - 运行时UI
  • 【项目复现】——DDoS-SDN Detection Project
  • Nginx + Lua + Redis:打造智能 IP 黑名单系统
  • 「Mac畅玩鸿蒙与硬件14」鸿蒙UI组件篇4 - Toggle 和 Checkbox 组件
  • Conditional DETR论文笔记