广告位联系
返回顶部
分享到

停止编写API函数原因介绍

正则表达式 来源:互联网 作者:佚名 发布时间:2022-09-30 12:25:03 人浏览
摘要

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

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

// api/users.js

// 创建

export function createUser(userFormValues) {

  return fetch('users', { method: 'POST', body: userFormValues });

}

// 查询

export function getListOfUsers(keyword) {

  return fetch(`/users?keyword=${keyword}`);

}

export function getUser(id) {

  return fetch(`/users/${id}`);

}

// 更新

export updateUser(id, userFormValues) {

  return fetch(`/users/${is}`, { method: 'PUT', body: userFormValues });

}

// 删除

export function removeUser(id) {

  return fetch(`/users/${id}`, { method: 'DELETE' });

}

类似的功能可能存在于其他实体,例如:城市、产品、类别...但是我们可以用一个简单的函数调用来代替这些函数:

1

2

3

4

// apis/users.js

export const users = crudBuilder('/users');

// apis/cities.js

export const cities = crudBuilder('/regions/cities');

然后像这样去使用:

1

2

3

4

5

users.create(values);

users.show(1);

users.list('john');

users.update(values);

users.remove(1);

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

  • 减少了代码行数:你编写的代码,和当你离开公司时其他人维护的代码
  • 强制执行 API 函数的命名约定,这可以增加代码的可读性和可维护性。例如你已经见过的函数名称: getListOfUsers, getCities, getAllProducts, productIndex, fetchCategories等, 他们都在做相同的事情,那就是“获取实体列表”。使用这种方法,你将始终拥有entityName.list()函数,并且团队中的每个人都知道这一点。

所以,让我们创建crudBuilder()函数,然后再添加一些糖。

一个非常简单的 CRUD 构造器

对于上边的简单示例,crudBuilder()函数将非常简单:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

export function crudBuilder(baseRoute) {

  function list(keyword) {

    return fetch(`${baseRoute}?keyword=${keyword}`);

  }

  function show(id) {

    return fetch(`${baseRoute}/${id}`);

  }

  function create(formValues) {

    return fetch(baseRoute, { method: 'POST', body: formValues });

  }

  function update(id, formValues) {

    return fetch(`${baseRoute}/${id}`, { method: 'PUT', body: formValues });

  }

  function remove(id) {

    return fetch(`${baseRoute}/${id}`, { method: 'DELETE' });

  }

  return {

    list,

    show,

    create,

    update,

    remove

  };

}

假设约定 API 路径并且给相应实体提供一个路径前缀,他将返回该实体上调用 CRUD 操作所需的所有方法。

但老实说,我们知道现实世界的应用程序并不会那么简单。在将这种方法应用于我们的项目时,有很多事情需要考虑:

  • 过滤:列表 API 通常会提供许多过滤器参数
  • 分页:列表 API 总是分页的
  • 转换:API 返回的值在实际使用之前可能需要进行一些转换
  • 准备:formValues对象在发送给 API 之前需要做一些准备工作
  • 自定义接口:更新特定项的接口不总是${baseRoute}/${id}

因此,我们需要可以处理更多复杂场景的 CRUD 构造器。

高级 CRUD 构造器

让我们通过上述方法来构建一些日常中我们真正使用的东西。

过滤

首先,我们应该在 list输出函数中处理更加复杂的过滤。每个实体列表可能有不同的过滤器并且用户可能应用了其中的一些过滤器。因此,我们不能对应用过滤器的形状和值有任何假设,但是我们可以假设任何列表过滤都可以产生一个对象,该对象为不同的过滤器名称指定了一些值。例如,我们可以过滤一些用户:

1

2

3

4

const filters = {

  keyword: 'john',

  createdAt: new Date('2020-02-10')

};

另一方面,我们不知道这些过滤器应该如何传递给 API,但是我们可以假设(跟 API 提供方进行约定)每一个过滤器在列表 API 中都有一个相应的参数,可以以'key=value'URL 查询参数的形式被传递。

因此我们需要知道如何将应用的过滤器转换成相对应的 API 参数来创建我们的 list 函数。这可以通过将 transformFilters 参数传递给 crudBuilder() 来完成。举一个用户的例子:

1

2

3

4

5

6

7

8

9

10

function transformUserFilters(filters) {

  const params = [];

  if (filters.keyword) {

    params.push(`keyword=${filters.keyword}`);

  }

  if (filters.createdAt) {

    params.push(`create_at=${dateUtility.format(filters.createdAt)}`);

  }

  return params;

}

现在我们可以使用这个参数来创建 list 函数了。

1

2

3

4

5

6

7

8

9

export function crudBuilder(baseRoute, transformFilters) {

  function list(filters) {

    let params = transformFilters(filters)?.join('&');

    if (params) {

      params += '?';

    }

    return fetch(`${baseRoute}${params}`);

  }

}

转换和分页

从 API 接收的数据可能需要进行一些转换才能在我们的应用程序中使用。例如,我们可能需要将 snake_case 转换成驼峰命名或将一些日期字符串转换成用户时区。

此外,我们还需要处理分页。

我们假设来自 API 的分页数据都按照如下格式(与 API 提供者约定):

1

2

3

4

{

  data: [], // 实体对象列表

  pagination: {...} // 分页信息

}

因此,我们需要知道如何转换单个实体对象。然后我们可以遍历列表对象来转换他们。为此,我们需要一个 transformEntity 函数作为 crudBuilder 的参数。

1

2

3

4

5

6

7

8

9

10

11

export function crudBuilder(baseRoute, transformFilters, transformEntity, ) {

  function list(filters) {

    const params = transformFilters(filters)?.join('&');

    return fetch(`${baseRoute}?${params}`)

      .then((res) => res.json())

      .then((res) => ({

        data: res.data.map((entity) => transformEntity(entity)),

        pagination: res.pagination

      }));

  }

}

list() 函数我们就完成了。

准备

对于 create 和 update 函数,我们需要将 formValues 转换成 API 需要的格式。例如,假设我们在表单中有一个 City 的城市选择对象。但是 create API 只需要 city_id。因此,我们需要一个执行以下操作的函数:

1

const prepareValue = formValue => ({city_id: formValues.city.id});

这个函数会根据用例返回普通对象或者 FormData,并且可以将数据传递给 API:

1

2

3

4

5

6

7

8

export function crudBuilder(baseRoute, transformFilters, transformEntity, prepareFormValues) {

  function create(formValues) {

    return fetch(baseRoute, {

      method: 'POST',

      body: prepareFormValues(formValues)

    });

  }

}

自定义接口

在一些少数情况下,对实体执行某些操作的 API 接口不遵循相同的约定。例如,我们不能使用 /users/${id} 来编辑用户,而是使用 /edit-user/${id}。对于这些情况,我们应该指定一个自定义路径。

在这里我们允许覆盖 crud builder 中使用的任何路径。注意,展示、更新、移除操作的路径可能取决于具体实体对象的信息,因此我们必须使用函数并传递实体对象来获取路径。

我们需要在对象中获取这些自定义路径,如果没有指定,就退回到默认路径。像这样:

1

2

3

4

5

6

7

const paths = {

  list: 'list-of-users',

  show: (userId) => `users/with/id/${userId}`,

  create: 'users/new',

  update: (user) => `users/update/${user.id}`,

  remove: (user) => `delete-user/${user.id}`

};

最终的 BRUD 构造器

这是创建 CRUD 函数的最终代码。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

export function crudBuilder(baseRoute, transformFilters, transformEntity, prepareFormValues, paths) {

  function list (filters) {

    const path = paths.list || baseRoute;

    let params = transformFilters(filters)?.join('&');

    if (params) {

      params += '?';

    }

    return fetch(`${path}${params}`)

      .then((res) => res.json())

      .then(() => ({

        data: res.data.map(entity => transformEntity(entity)),

        pagination: res.pagination

      }));

  }

  function show(id) {

    const path = paths.show?.(id) || `${baseRoute}/${id}`;

    return fetch(path)

      .then((res) => res.json())

      .then((res => transformEntity(res)));

  }

  function create(formValues) {

    const path = paths.create || baseRoute;

    return fetch(path, { method: 'POST', body: prepareFormValues(formValues) });

  }

  function update(id, formValues) {

    const path = paths.update?.(id) || `${baseRoute}/${id}`;

    return fetch(path, { method: 'PUT', body: formValues });

  }

  function remove(id) {

    const path = paths.remove?.(id) || `${baseRoute}/${id}`;

    return fetch(path, { method: 'DELETE' });

  }

  return {

    list,

    show,

    create,

    update,

    remove

  }

}

Saeed Mosavat: Stop writing API functions https://dev.to/saeedmosavat/stop-writing-api-functions-3693


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。

您可能感兴趣的文章 :

原文链接 : https://juejin.cn/post/7147993043923107870
相关文章
  • 正则表达式校验日期时间格式的方法
    日期部分校验 概念 首先,我们先了解2个概念: 1、合法的日期范围: DateTime值类型表示值范围在公元(基督纪元)0001 年 1 月 1 日午夜 12
  • 如何使用正则表达式对输入数字进行匹配

    如何使用正则表达式对输入数字进行匹配
    最近有一个区间范围限制,一般255数字以下的都能在网上薅到,但是需要弄一个int16、int32、int64范围的输入限制......在网上逛了很久都没找
  • 最实用的正则表达式的整理

    最实用的正则表达式的整理
    想要白嫖正则是吧?本篇就一次给你个够!先冲 100 个!(如果还觉得不够就评论反馈后再加,本篇持续更新加码!!) 点赞再看,养成好
  • 停止编写API函数原因介绍
    RESTFUL API 通常提供在不同实体上执行增删改查(CRUD)操作的一组接口。我们通常在我们的前端项目中为这些每一个接口提供一个函数,这些
  • 正则表达式的基本语法汇总介绍

    正则表达式的基本语法汇总介绍
    1.正则表达式的基本语法 1.1两个特殊符号 ^ 和 $ ^ 正则表达式的起始符 ^tom 表示所有以tom开头的字符串 $ 正则表达式的结束符 lucy$ 表示所有
  • 正则表达式基础语法以及应用介绍

    正则表达式基础语法以及应用介绍
    一、正则表达式 1、基本介绍 ? 概述 一个正则表达式,就是用某种模式去匹配字符串的一个公式。很多人因为它们看上去比较古怪而且复杂
  • 正则表达式从HTML中匹配img标签的图片地址

    正则表达式从HTML中匹配img标签的图片地址
    前言 有玩过爬虫的人应该都有过在又臭又长的HTML中找寻信息的经历,虽然有各种工具和各种框架可以辅助查找,但是解析HTML的规则也是人
  • Snort中pcre和正则表达式的使用介绍

    Snort中pcre和正则表达式的使用介绍
    1. 题目描述 If snort see two packets in a TCP flow with first packet has login or Initial in payload, destination port is 3399;and second packet has a IPv4Address:Portstring(E.g
  • 在nest.js中通过正则表达式正确设置验证的方法

    在nest.js中通过正则表达式正确设置验证的方法
    下面看下nest.js正则表达式设置验证的方法,代码如下所示: 1 2 3 4 import { IsNotEmpty, Length, Matches, Max, Min } from class-validator; const phoneReg = /^1(3
  • shell脚本中的正则表达式介绍
    正则表达式的概念及特点: 正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计