都2023了,不会有人手撸API函数吧

简介: 都2023了,不会有人手撸API函数吧如果你正在开发一个前端程序,后端有指定规范的 API, 那你该看看这篇文章啦~

都2023了,不会有人手撸API函数吧

如果你正在开发一个前端程序,后端有指定规范的 API, 那你该看看这篇文章啦~

本文章示例用到了TypeScript,如果觉得不适,看一下核心代码即可。

业务场景举例

API 通常是提供在不同实体上执行增删改查(CRUD)造作的一组接口。我们通常在我们的前端项目中为这些每一个接口提供一个函数,这些函数的功能非常的相似,只是为了服务于不用的实体。举个例子,假设我们有这些函数。

// api/user.ts

import http from '@/utils/http';

// 登录参数
export interface LoginData {
   
  /** 登陆编码 */
  loginCode: string;
  password: string;
}

/** 用户信息 */
export interface UserInfo {
   
  /** 状态 */
  status: string;
  /** 创建人 */
  createBy: string;
  /** 创建时间 */
  createDate: string;
  /** 更新人 */
  updateBy: string;
  /** 更新时间 */
  updateDate: string;
  remarks: string | null;
  /** 用户编码 */
  userCode: string;
  /** 登陆编码 */
  loginCode: string;
  /** 用户名 */
  userName: string;
  /** 密码 */
  password: string;
  /** 邮件 */
  email: string;
  /** 手机 */
  mobile: string | null;
  /** 电话 */
  phone: string | null;
  /** 性别 */
  sex: string;
  /** 头像 */
  avatar: string | null;
  /** 个性签名 */
  sign: string | null;
  /** 微信开发id */
  wxOpenId: string | null;
  /** 手机imei */
  mobileImei: string | null;
  /** 用户类型 */
  userType: string;
  /** 用户类型引用编号 */
  refCode: string | null;
  /** 用户类型引用名称 */
  refName: string | null;
  /** 管理员类型 */
  mgrType: string;
  /** 密码强度等级 */
  pwdSecurityLevel: string | null;
  /** 用户权重 */
  userWeight: number;
}

/** 登录信息 */
export interface LoginInfo {
   
  tokenName: string;
  tokenValue: string;
  isLogin: boolean;
  loginId: string;
  loginType: string;
  tokenTimeout: number;
  sessionTimeout: number;
  tokenSessionTimeout: number;
  tokenActivityTimeout: number;
  loginDevice: string;
  tag: string;
}

export interface LoginRes {
   
  loginInfo: LoginInfo;
  userInfo: UserInfo;
}
/** 登录接口 */
export function login(data: LoginData) {
   
  return http.post<LoginRes>({
    url: '/login', data });
}

/** 登出接口 */
export function logout() {
   
  return http.post<null>({
    url: '/logout' });
}
/** 获取当前登录的用户信息 */
export function getLoginUserInfo() {
   
  return http.get<UserInfo>({
    url: '/loginUserInfo' });
}
/** 获取当前登录信息 */
export function getTokenInfo() {
   
  return http.get<LoginInfo>({
    url: '/tokenInfo' });
}

类似的功能可能存在于其他实体,例如:角色、权限、用户...但是我们可以用一个简单的函数调用来代替这些函数:

// api/system-privilege/users.ts

import {
    ServiceProxy } from '@/shared';
import {
    UserInfo } from '@/api/user';
import {
    ListDataRes } from '@/api/common';

// 参数接口
export interface ListDataParams {
   
  userName?: string;
}
export interface SaveParams {
   
  userCode?: string;
  loginCode: string;
  userName?: string;
  mobile?: string;
  email?: string;
  sex?: string;
  sign?: string;
  userType: string;
  userWeight: number;
  mgrType: string;
}

// 核心
const service = new ServiceProxy('/api/sys/user');

/**
 * 获取用户列表
 * @param {object} params ListDataParams
 * @param {string} params.userName
 * @returns
 */
export function getPaged(
  params: ListDataParams
): Promise<ListDataRes<UserInfo>> {
   
  return service.getPaged(params);
}

/**
 * 修改或新增用户
 * @param {object} params 用户保存实体
 * @param {string} params.userCode 用户编码,用户id,为空则新增,不为空则修改
 * @param {string} params.loginCode 登陆编码,用户登陆的账号
 * @param {string} params.userName 用户名
 * @param {string} params.mobile 手机
 * @param {string} params.email 邮件
 * @param {string} params.sex 性别
 * @param {string} params.sign 个性签名
 * @param {string} params.userType 用户类型
 * @param {number} params.userWeight 用户权重
 * @param {string} params.mgrType 管理员类型
 * @returns
 */
export function createOrUpdate(params: SaveParams): Promise<null> {
   
  return service.createOrUpdate(params);
}

/**
 * 获取用户信息
 * @param {string} params.id 类型主键
 * @returns
 */
export function getById(params: {
    id: string }): Promise<null> {
   
  return service.getById(params);
}
/**
 * 获取用户信息
 * @param {string} params.id 类型主键
 * @returns
 */
export function del(params: {
    id: string }): Promise<null> {
   
  return service.delete(params);
}

然后像这样去使用:

import {
    getPaged, createOrUpdate, getById } from '@/api/system-privilege/users';

// 一下返回的是Promise

getPaged({
    ...params.res, pageNum: params.pageNum, pageSize: params.pageSzie });
createOrUpdate(state.data);
getById({
    id: props.id })

你可能会问为什么?有一些很好的理由:

  • 减少了代码行数:你编写的代码,和当你离开公司时其他人维护的代码
  • 强制执行 API 函数的命名约定,这可以增加代码的可读性和可维护性
  • 同时 ServiceProxy 的实现使用的 class,当API不符合要求时,可以通过继承等方式进行扩展(业务场景:对接第三方接口)。

此处ServiceProxy就类似于一个高级可扩展的 CRUD 构造器。

高级构造器 ServiceProxy 的实现

以下便是ServiceProxy基础实现,如果觉得简单,是可以进行增强和扩展的哟。

import http from '@/utils/http';
import VAxios from '@/utils/http/Axios';

export default class ServiceProxies {
   
  private instance: VAxios;

  private baseUrl: string;

  private url: string;

  constructor(url?: string, baseUrl?: string, instance?: VAxios) {
   
    this.instance = instance || http;

    this.baseUrl = baseUrl !== undefined && baseUrl !== null ? baseUrl : '';

    this.url = url !== undefined && url !== null ? url : '';
  }

  /**
   * 获取列表数据
   * @returns
   */
  getPaged<T>(params: T) {
   
    return this.instance.post({
    url: this.url, data: {
    ...params } });
  }

  /**
   * 通过ID获取详细信息
   * @returns
   */
  getById<T>(params: T) {
   
    return this.instance.get({
    url: this.url, params: {
    ...params } });
  }

  /**
   * 通过拼接构造器与传入的api进行Get请求,类似扩展构造器的url
   * @param api 扩展api
   * @param params 参数值
   */
  getApi(api: string, params: any) {
   
    return this.instance.get({
   
      url: `${this.url}${api}`,
      params: {
    ...params },
    });
  }

  /**
   * 通过拼接构造器与传入的api进行Post请求,类似扩展构造器的url
   * @param api 扩展api
   * @param params 参数值
   */
  postApi(api: string, params: any) {
   
    return this.instance.post({
   
      url: `${this.url}${api}`,
      data: {
    ...params },
    });
  }

  /**
   * 通过拼接构造器与传入的api进行Put请求,类似扩展构造器的url
   * @param api 扩展api
   * @param params 参数值
   */
  putApi(api: string, params: any) {
   
    return this.instance.put({
   
      url: `${this.url}${api}`,
      data: {
    ...params },
    });
  }

  /**
   * 通过拼接构造器与传入的api进行Delete请求,类似扩展构造器的url
   * @param api 扩展api
   * @param params 参数值
   */
  deleteApi(api: string, params: any) {
   
    return this.instance.delete({
   
      url: `${this.url}${api}`,
      params: {
    ...params },
    });
  }

  /**
   * 新增或者编辑
   * @returns
   */
  createOrUpdate<T>(params: T) {
   
    return this.instance.put({
    url: this.url, params: {
    ...params } });
  }
}

用法:

import {
    ServiceProxy } from '@/shared';

const service = new ServiceProxy('/api/sys/user');
const service = new ServiceProxy('/api/sys/role');
const service = new ServiceProxy('/api/sys/menu');

// 然后再去编写业务逻辑代码
// 相关示例可以观看上述的用户示例

结尾

看到这里小伙伴们是不是有一种发现新大陆的感觉。

快动动你们的小手指敲起来吧~

当然,如果觉得有什么不合理的地方,可以指出来哦。

目录
相关文章
|
5月前
|
存储 JavaScript API
活用 Composition API 核心函数,打造卓越应用(上)
活用 Composition API 核心函数,打造卓越应用(上)
|
5月前
|
缓存 JavaScript 算法
活用 Composition API 核心函数,打造卓越应用(下)
活用 Composition API 核心函数,打造卓越应用(下)
|
2月前
|
JSON 前端开发 API
构建前端防腐策略问题之更新getMemoryUsagePercent函数以适应新的API返回格式的问题如何解决
构建前端防腐策略问题之更新getMemoryUsagePercent函数以适应新的API返回格式的问题如何解决
构建前端防腐策略问题之更新getMemoryUsagePercent函数以适应新的API返回格式的问题如何解决
|
18天前
|
网络协议 API Windows
MASM32编程调用 API函数RtlIpv6AddressToString,windows 10 容易,Windows 7 折腾
MASM32编程调用 API函数RtlIpv6AddressToString,windows 10 容易,Windows 7 折腾
|
20天前
|
存储 程序员 API
【收藏】非API函数检测操作系统类型
【收藏】非API函数检测操作系统类型
|
2月前
|
Linux API
Linux源码阅读笔记07-进程管理4大常用API函数
Linux源码阅读笔记07-进程管理4大常用API函数
|
5月前
|
人工智能 关系型数据库 Serverless
Serverless 应用引擎常见问题之API生成的函数镜像改为自定义的镜像如何解决
Serverless 应用引擎(Serverless Application Engine, SAE)是一种完全托管的应用平台,它允许开发者无需管理服务器即可构建和部署应用。以下是Serverless 应用引擎使用过程中的一些常见问题及其答案的汇总:
|
2月前
|
API 开发工具 图形学
PicoVR Unity SDK⭐️五、常用API接口函数一览
PicoVR Unity SDK⭐️五、常用API接口函数一览
|
3月前
|
API 运维
开发与运维函数问题之filter操作符在Gather API中的实现方式如何解决
开发与运维函数问题之filter操作符在Gather API中的实现方式如何解决
18 1
|
3月前
|
API 运维
开发与运维函数问题之Gather API与Stream Collector的区别如何解决
开发与运维函数问题之Gather API与Stream Collector的区别如何解决
24 1