记录--前端实用小技巧: 自动合并的网络请求

这篇具有很好参考价值的文章主要介绍了记录--前端实用小技巧: 自动合并的网络请求。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

记录--前端实用小技巧: 自动合并的网络请求

我们经常会遇到一个场景,比如在一个列表中批量获取用户的信息。

 

记录--前端实用小技巧: 自动合并的网络请求

如果我们一次性往后端发送几十条请求是非常愚蠢的事情。此时我们就要学会如何使用批量获取的逻辑。

但是批量获取有一个问题就是,我需要在用户列表项的上层去获取,然后再把结果分发给下层

此时的结构如下:

const List = () => {
	return itemInfoList.map((info) => <Item info={info} />)
}

这样我们就可以很方便的解决我们遇到的问题啦,因为是一个接口获取的结果嘛。

但是!这种写法不利于维护。因为 <Item /> 组件的依赖过于庞大,是一个完整的对象。对于其他组件来说很难复用,大概率这个组件就只能在一处地方用了。那么我想要复用怎么办呢?

那就是写成如下形式

const List = () => {
	return ids.map((id) => <Item id={id} />)
}

然后 <Item /> 组件内部就可以根据传入的id自行获取对应的数据,然后自我处理了。

那么不就遇到开头这个问题了嘛?如果一次渲染几十个用户组件,那么不就同时向后端发送几十个网络请求了嘛!

这时候我们需要实现一个逻辑,自动收集并合并可以被合并的网络请求。

完整代码如下:

interface QueueItem<T, R> {
  params: T;
  resolve: (r: R) => void;
  reject: (reason: unknown) => void;
}

/**
 * 创建一个自动合并请求的函数
 * 在一定窗口期内的所有请求都会被合并提交合并发送
 * @param fn 合并后的请求函数
 * @param windowMs 窗口期
 */
export function createAutoMergedRequest<T, R>(
  fn: (mergedParams: T[]) => Promise<R[]>,
  windowMs = 200
): (params: T) => Promise<R> {
  let queue: QueueItem<T, R>[] = [];
  let timer: number | null = null;

  async function submitQueue() {
    timer = null; // 清空计时器以接受后续请求
    const _queue = [...queue];
    queue = []; // 清空队列

    try {
      const list = await fn(_queue.map((q) => q.params));
      _queue.forEach((q1, i) => {
        q1.resolve(list[i]);
      });
    } catch (err) {
      _queue.forEach((q2) => {
        q2.reject(err);
      });
    }
  }

  return (params: T): Promise<R> => {
    if (!timer) {
      // 如果没有开始窗口期,则创建
      timer = window.setTimeout(() => {
        submitQueue();
      }, windowMs);
    }

    return new Promise<R>((resolve, reject) => {
      queue.push({
        params,
        resolve,
        reject,
      });
    });
  };
}

用法是:

const fetchUserInfo = createAutoMergedRequest<string, UserBaseInfo>(
  async (userIds) => {
    const { data } = await request.post('/api/user/getUserInfoList', {
      userIds,
    });

    return data;
  }
);

fetchUserInfo(1)
fetchUserInfo(2)
fetchUserInfo(3)

接下来我们来解读一下代码。

先看整体架构。 createAutoMergedRequest 函数返回了一个匿名函数,来接受参数并返回结果请求。但是需要注意的是我们定义了两个泛型 TR 。其中 createAutoMergedRequest 接受的 fn 参数的类型是 (mergedParams: T[]) => Promise<R[]> ,而返回的函数定义是 (params: T): Promise<R> 。这是因为他会自动把请求的结果拆分成独立的返回值返回到对应的调用处。

我们看返回的函数体:

if (!timer) {
    // 如果没有开始窗口期,则创建
    timer = window.setTimeout(() => {
      submitQueue();
    }, windowMs);
  }

  return new Promise<R>((resolve, reject) => {
    queue.push({
      params,
      resolve,
      reject,
    });
  });

首先判断闭包中是否存在定时器 timer, 如果没有则创建一个timer,在 windowMs 后执行 submitQueue 方法。我们把 windowMs 定义为窗口期,在这个窗口期内调用该函数的请求都会被收集起来。

然后创建返回一个promise,把参数和promise相关的下一步操作都推到 queue 中。

等到若干次调用后,定时器到时间了,唤起回调执行submitQueue 方法,我们来看看 submitQueue 的操作。

async function submitQueue() {
  timer = null; // 清空计时器以接受后续请求
  const _queue = [...queue];
  queue = []; // 清空队列
  const ret = fn(_queue.map((q) => q.params));

  try {
    const list = await fn(_queue.map((q) => q.params));
    _queue.forEach((q1, i) => {
      q1.resolve(list[i]);
    });
  } catch (err) {
    _queue.forEach((q2) => {
      q2.reject(err);
    });
  }
}

执行前我们会做一些前置工作,清理 timer, 清理 queue 并把队列里的项单独存放起来,防止影响到下一次执行。

然后我们通过 fn(_queue.map((q) => q.params)) 来把队列中的参数拿出来,传给 fn 调用。此时的 fn 就会接收到一个数组。并确保返回的结果也是一个同等大小且一一对应的数据即可。如果请求无误,我们就循环队列,把结果通过队列中记录的 resolve 把结果返回给我们之前创建的promise。

这样我们就实现了一个工具函数,我们可以在一个窗口期内收集到多个网络请求,并把他们汇聚成一个请求发送到后端。后端结果返回回来后,我们再把请求结果拆分分发给独立的调用方。

记录--前端实用小技巧: 自动合并的网络请求

 

记录--前端实用小技巧: 自动合并的网络请求

本文转载于:

https://juejin.cn/post/7259275893796388925

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

 记录--前端实用小技巧: 自动合并的网络请求文章来源地址https://www.toymoban.com/news/detail-633083.html

到了这里,关于记录--前端实用小技巧: 自动合并的网络请求的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 记录--前端实现并发请求限制

    前两天我的新同事告诉我一个困扰着他的问题,就是低代码平台中存在很多模块,这些模块的渲染是由模块自身处理的,简言之就是组件请求了自己的数据,一个两个模块还好,要是一次请求了几十个模块,就会出现请求阻塞的问题,而且模块的请求都特别大。 大量的并发请

    2024年02月08日
    浏览(36)
  • 记录--前端中 JS 发起的请求可以暂停吗

    在前端中,JavaScript(JS)可以使用XMLHttpRequest对象或fetch API来发起网络请求。然而,JavaScript本身并没有提供直接的方法来暂停请求的执行。一旦请求被发送,它会继续执行并等待响应。 尽管如此,你可以通过一些技巧或库来模拟请求的暂停和继续执行。下面是一种常见的方法

    2024年02月05日
    浏览(38)
  • 实用技巧:Linux上实现OpenGauss数据库远程连接,方便的跨网络数据操作

    openGauss是一款开源关系型数据库管理系统,采用木兰宽松许可证v2发行。openGauss内核深度融合华为在数据库领域多年的经验,结合企业级场景需求,持续构建竞争力特性. 结合cpolar 内网穿透工具,即可实现远程访问本地openGauss,实现远程访问,下面介绍从Linux安装到远程访问的方式

    2024年02月08日
    浏览(49)
  • Objective-C网络请求开发的高效实现方法与技巧

    在移动应用开发中,网络请求是一项至关重要的技术。Objective-C作为iOS平台的主要开发语言之一,拥有丰富的网络请求开发工具和技术。本文将介绍如何利用Objective-C语言实现高效的网络请求,以及一些实用的技巧和方法。 Objective-C是一种基于C语言的面向对象编程语言,它具

    2024年04月14日
    浏览(36)
  • 高级网络调试技巧:使用Charles Proxy捕获和修改HTTP/HTTPS请求

    目录 1、简介 2、安装和设置 3、捕获HTTP/HTTPS请求 4、修改HTTP/HTTPS请求 5、断点和日志记录 6、过滤和排序请求 7、导出和导入数据 8、高级功能和技术 9、实际应用 总结 在调试网络应用时,了解如何捕获和修改HTTP/HTTPS请求是非常有用的。这些技巧对于识别和解决问题,以及测

    2024年02月08日
    浏览(69)
  • 使用 Axios 实现前端网络请求

    在现代的 Web 开发中,网络请求是不可或缺的一部分。前端开发者需要与后端服务器通信以获取数据、发送表单、或者执行其他操作。在过去,开发者通常使用 XMLHttpRequest (XHR) 对象来处理这些请求,但现在有了更加现代化和简洁的解决方案,其中一种就是 Axios。 Axios 是一个基

    2024年03月23日
    浏览(44)
  • 前端uniapp封装网络请求详情教程

    1,common文件夹下http.api.js,定义接口 2,common文件夹下http.interceptor.js,请求封装 3,全局数据定义 store文件夹下index.js 注意:vuex的使用前要先导入vuex(npm i vuex),在该方法中还需导入vuex-persistedstate(npm i vuex-persistedstate) 4,main.js中声明(例子中用的比较杂,挑有用的使用) 5,接

    2024年02月02日
    浏览(39)
  • 记录--前端无感知刷新token & 超时自动退出

    因为http请求是无状态的,是一次性的,请求之间没有任何关系,服务端无法知道请求者的身份,所以需要鉴权,来验证当前用户是否有访问系统的权限。 以oauth2.0授权码模式为例: 每次请求资源服务器时都会在请求头中添加 Authorization: Bearer access_token 资源服务器会先判断t

    2024年02月03日
    浏览(47)
  • 前端自动化测试工具 Cypress 试用调研记录

    目录 前言 环境准备 1.工具:vs code;环境:node.js。 2.安装 cypress 3.安装插件: 4.配置: 5.启动命令: helloworld: 第一个用例 元素定位方式 使用 request 请求进行登录 提取登录方法为公共方法 命令行执行所有用例 解决 chrome 下的跨域问题: 生成 Junit-allure 报表 生成 mocha awsome

    2024年02月16日
    浏览(43)
  • 前端Vue uni-app简单实用通用标签栏自动换行 自适应高度 可设置行数 可改标签颜色

    随着技术的发展,开发的复杂度也越来越高,传统开发方式将一个系统做成了整块应用,经常出现的情况就是一个小小的改动或者一个小功能的增加可能会引起整体逻辑的修改,造成牵一发而动全身。通过组件化开发,可以有效实现单独开发,单独维护,而且他们之间可以随

    2024年02月05日
    浏览(80)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包