iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >停止编写API函数原因示例分析
  • 495
分享到

停止编写API函数原因示例分析

2024-04-02 19:04:59 495人浏览 安东尼
摘要

目录正文你可能会问为什么?有一些很好的理由:一个非常简单的 CRUD 构造器高级 CRUD 构造器过滤转换和分页准备自定义接口最终的 BRUD 构造器正文 RESTFUL api 通

正文

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

// 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' });
}

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

// apis/users.js
export const users = crudBuilder('/users');
// apis/cities.js
export const cities = crudBuilder('/regions/cities');

然后像这样去使用:

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()函数将非常简单:

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

const filters = {
  keyword: 'john',
  createdAt: new Date('2020-02-10')
};

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

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

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 函数了。

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 提供者约定):

{
  data: [], // 实体对象列表
  pagination: {...} // 分页信息
}

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

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() 函数我们就完成了。

准备

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

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

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

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 中使用的任何路径。注意,展示、更新、移除操作的路径可能取决于具体实体对象的信息,因此我们必须使用函数并传递实体对象来获取路径。

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

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 函数的最终代码。

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

以上就是停止编写 API函数原因示例分析的详细内容,更多关于停止编写 API 函数的资料请关注编程网其它相关文章!

--结束END--

本文标题: 停止编写API函数原因示例分析

本文链接: https://www.lsjlt.com/news/168601.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 停止编写API函数原因示例分析
    目录正文你可能会问为什么?有一些很好的理由:一个非常简单的 CRUD 构造器高级 CRUD 构造器过滤转换和分页准备自定义接口最终的 BRUD 构造器正文 RESTFUL API 通...
    99+
    2024-04-02
  • PHPcms停止更新的原因分析
    PHPcms停止更新的原因分析 随着互联网和网络技术的不断发展,各种类型的内容管理系统(CMS)层出不穷,其中PHPcms曾经是一个备受关注的开源CMS系统。然而,近年来 PHPcms...
    99+
    2024-03-14
    更新 php cms 技术趋势
  • vue-next函数式api的示例分析
    小编给大家分享一下vue-next函数式api的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!setupsetup 会作...
    99+
    2024-04-02
  • JavaScript函数式编程示例分析
    目录函数式编程函数柯理化(Curring)Compose场景案例总结函数式编程 1.函数式编程指的是函数的映射关系 2.vue3、react16.8的函数组件推动了前端函数编程 3....
    99+
    2022-11-13
    JavaScript函数式编程 JS函数式编程
  • Java函数编程的示例分析
    小编给大家分享一下Java函数编程的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!一、函数编程Lambda我们可以将lambda表达式视为一个匿名函数,可以将其分配给变量并传递给方法,该方法接受函数接口作为参数。L...
    99+
    2023-06-25
  • ZooKeeper Java API编程的示例分析
    这篇文章主要为大家展示了“ZooKeeper Java API编程的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“ZooKeeper Java API编程的示例分析”这篇文章吧。开发应用...
    99+
    2023-05-30
    zookeeper java
  • JavaScript函数式编程的示例分析
    这篇文章给大家分享的是有关JavaScript函数式编程的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。看过许多关于函数式编程的讲解,但是其中大部分是停留在理论层面,还有...
    99+
    2024-04-02
  • python函数式编程的示例分析
    这篇文章给大家分享的是有关python函数式编程的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。python可以做什么Python是一种编程语言,内置了许多有效的工具,Python几乎无所不能,该语言通俗...
    99+
    2023-06-14
  • js中函数式编程的示例分析
    这篇文章主要为大家展示了“js中函数式编程的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“js中函数式编程的示例分析”这篇文章吧。(1)平常写的函数大多...
    99+
    2024-04-02
  • base64编码原理的示例分析
    这篇文章将为大家详细讲解有关base64编码原理的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。 base64编码原理 最近在做将文件转成base64编码,并...
    99+
    2024-04-02
  • mac下redis安装、设置、启动停止的示例分析
    小编给大家分享一下mac下redis安装、设置、启动停止的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!需要下载rele...
    99+
    2024-04-02
  • Visual Basic代码编写的示例分析
    这篇文章主要介绍了Visual Basic代码编写的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。图 3 中的代码显示一个示例,该示例对上述 Visual Basic...
    99+
    2023-06-17
  • 阿里云 ECS 一直是停止中原因分析与解决方案
    阿里云的 Elastic Compute Service(简称ECS)是阿里云提供的一种基于虚拟化技术的可扩展计算服务。然而,最近有些用户反馈说阿里云 ECS一直是停止中,无法正常使用。本文将对这个问题进行详细说明,包括问题的原因分析以及...
    99+
    2023-11-03
    阿里 解决方案 原因
  • Node.js函数的示例分析
    这篇文章将为大家详细讲解有关Node.js函数的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。内容:普通函数,匿名函数,函数传递是如何让HTTP服务器工作的###...
    99+
    2024-04-02
  • js函数的示例分析
    这篇文章主要介绍了js函数的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。函数1 函数默认值func = (l,...
    99+
    2024-04-02
  • mysql函数的示例分析
    这篇文章将为大家详细讲解有关mysql函数的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一.内置函数1.数学函数rand()round(num)ceil(num...
    99+
    2024-04-02
  • JavaScript函数的示例分析
    这篇文章给大家分享的是有关JavaScript函数的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。什么是函数函数是完成某一功能的代码段函数是可重复执行的代码段函数方便管理...
    99+
    2024-04-02
  • 函数参数的示例分析
    这篇文章将为大家详细讲解有关函数参数的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。函数的参数(实参和形参):形参变量只有在被调用时才分配内存单元,在调用结束时, 即刻释放所分配的内存单元。因此,...
    99+
    2023-06-15
  • Linux函数原型实例分析
    本篇内容主要讲解“Linux函数原型实例分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Linux函数原型实例分析”吧!引言条件变量是利用线程间共享的全局变量...
    99+
    2024-04-02
  • Python函数式编程装饰器的示例分析
    这篇文章给大家分享的是有关Python函数式编程装饰器的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。一、装饰器的本质:装饰器(decorator)本质是函数闭包(function closure)的语法...
    99+
    2023-06-29
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作