【JavaScript进阶】掌握异步请求调度:实现隔一秒钟发一个请求

背景

最近在与后端协同调试一个接口,由于业务逻辑较为复杂且处理时间较长,单个请求的处理时长需 5 秒以上。为了避免请求过于频繁,后端对该接口进行了 IP 限制,每秒仅允许一个请求,同时同一时间最多处理 5 个请求。在此记录实现过程。

一、限频实现

首先,我们需要实现每隔一秒发送一个异步请求。为此,我们可以使用 setTimeout 函数进行延时调用。具体操作步骤如下:

  1. 创建一个 async 函数,用于发起异步请求。
  2. 在循环中使用 setTimeout 函数实现延时调用,并将异步请求函数作为参数传递给 setTimeout
  3. 利用 数组mapPromise.all 实现异步请求。
ts 复制代码
const handRequest = async () => {
    const res = await request('http://localhost:9000/test');
    return res;
  };

const requestList = async () => {
    const requests = new Array(5).fill('').map((_, index) => {
      return new Promise((resolve) => {
        setTimeout(() => {
          console.log(`Request ${index} started: ${new Date().getTime()}`);

          handRequest().then((res) => resolve(res));
        }, index * 1000);
      });
    });
    
    const res = await Promise.all(requests);

    console.log(res);
};

二、调度实现

实现每隔一秒发送一个请求相对简单。但第二个需求是,同一时间最多只能处理 5 个请求。若请求数大于 5,我们该如何处理?这就涉及到调度问题。

为了更高效地实现异步请求调度,我们可以参考 GitHub 上的 async-pool 仓库。该库提供了一个简易的异步任务池,可方便地控制异步任务的并发数量。

首先,我们需要安装这个库:

bash 复制代码
npm install tiny-async-pool

然后在代码中引入:

ts 复制代码
import asyncPool from "tiny-async-pool";

现在,我们可以使用 async-pool 来实现我们的业务逻辑。

  • 对于前 5 个请求(index < 5),需要每隔 1 秒发送一个;
  • 对于大于 5 个的请求(index >= 5),可以立即发出(因为接口的逻辑处理时间大于 5 秒)。

代码实现

下面是具体的代码实现:

ts 复制代码
const handRequest = async () => {
    const res = await request('http://localhost:9000/test');
    return res;
  };

const requestList = async (index) => {
    return index < 5
      ? new Promise((resolve) => {
          setTimeout(() => {
            console.log(`Request ${index} started: ${new Date().getTime()}`);

            handRequest().then((res) => resolve(res));
          }, index * 1000);
        })
      : handRequest();
};

const requestPool = async () => {
    // 最大并发 5 个请求
    for await (const value of asyncPool(5, Array.from({ length: 10 }, (_, index) => index), (index: number) => requestList(index))) {
      console.log(`Request end: ${new Date().getTime()}`);
    }
};

在这个示例中,我们使用了 async-pool 库来实现请求调度。对于前 5 个请求(index 小于 5),它们会被延迟 1 秒发出。之后,每当有一个请求完成,就会立即发出一个新的请求,确保始终有 5 个请求在处理,直至所有请求都处理完毕。

执行这段代码,你将会看到如下输出:

ts 复制代码
Request started: 1699934326029
Request started: 1699934326974
Request started: 1699934327969
Request started: 1699934328973
Request started: 1699934329974
Request end: 1699934336047
Request started: 1699934336047
Request end: 1699934336981
Request started: 1699934336981
Request end: 1699934337976
Request started: 1699934337976
Request end: 1699934337994
Request started: 1699934337994
Request end: 1699934346050
Request started: 1699934346051
Request end: 1699934346985
Request end: 1699934347980
Request end: 1699934356053
Request end: 1699934357983
Request end: 1699934366057

可以看到,我们成功实现了每秒仅允许一个请求,同时同一时间最多处理 5 个请求

四、总结

本文向大家展示了如何在JavaScript中实现隔一秒钟发一个异步请求的功能,并参考GitHub上的async-pool仓库进行实现。希望通过本文的讲解,能够帮助大家更好地理解异步请求调度,提高自己的开发水平。

相关推荐
菲力蒲LY2 分钟前
输入搜索、分组展示选项、下拉选取,全局跳转页,el-select 实现 —— 后端数据处理代码,抛砖引玉展思路
java·前端·mybatis
MickeyCV1 小时前
Nginx学习笔记:常用命令&端口占用报错解决&Nginx核心配置文件解读
前端·nginx
祈澈菇凉2 小时前
webpack和grunt以及gulp有什么不同?
前端·webpack·gulp
十步杀一人_千里不留行2 小时前
React Native 下拉选择组件首次点击失效问题的深入分析与解决
javascript·react native·react.js
zy0101012 小时前
HTML列表,表格和表单
前端·html
初辰ge2 小时前
【p-camera-h5】 一款开箱即用的H5相机插件,支持拍照、录像、动态水印与样式高度定制化。
前端·相机
HugeYLH2 小时前
解决npm问题:错误的代理设置
前端·npm·node.js
六个点3 小时前
DNS与获取页面白屏时间
前端·面试·dns
道不尽世间的沧桑3 小时前
第9篇:插槽(Slots)的使用
前端·javascript·vue.js
bin91533 小时前
DeepSeek 助力 Vue 开发:打造丝滑的滑块(Slider)
前端·javascript·vue.js·前端框架·ecmascript·deepseek