使用 Promise 实现任务队列发送请求,实现最大请求数目限制
核心
- 设置最大请求数量,当前请求数量,待执行队列
- 调用时,创建一个新任务,然后判断是否达到最大请求数量,若达到则将任务追加到待执行队列,否则,则直接执行该任务。并返回Promise
- 创建任务时,需要返回一个函数,当该任务开始执行则当前数量加一。当任务执行完毕时使用finally,当前数量减一,并从待执行队列中取出新任务执行
实现
class limitPromise{
    constructor(max){
    this.max = max;
    this._count = 0;
    this._pendingTaskQueue = [];
  }
   /**
   * 调用器,将异步任务函数和它的参数传入
   * @param caller 异步任务函数,返回Promise的函数
   * @param args 异步任务函数的参数列表
   * @returns {Promise<unknown>} 返回一个新的Promise
   */
  call = (caller, ...arg) => {
    return new Promise((resolve, reject) => {
        let task = this._createTask(caller, arg, resolve, reject);
        if(this._count >= this.max) {
        this._pendingTaskQueue.push();
        }else{
        task();
        }
    });
    }
   /**
   * 创建一个任务
   * @param caller 实际执行的函数
   * @param args 执行函数的参数
   * @param resolve
   * @param reject
   * @returns {Function} 返回一个任务函数
   * @private
   */
     _createTask = (caller, arg, resolve, reject)=> {
     return () => {
       // 当前请求数量加一
       this._count++;
       // 实际上是在这里调用了异步任务,并将异步任务的返回(resolve和reject)抛给了上层
       caller(...arg)
         .then(resolve)
         .catch(reject)
         .finally(() => {
                // 任务队列的消费区,利用Promise的finally方法,在异步任务结束后,取出下一个任务执行
                this._count--;
                if(this._pendingTaskQueue.length){
                let task = this._pendingTaskQueue.shift();
                task();
                }
        })
     }
   }
}
使用
假设我们有一个网络请求模块,叫request.js,包含get和post方法,一般情况下,是这样使用的
const request = require('./request')
request.get('https://www.baidu.com')
  .then((res) => {
    // 处理返回结果
  })
  .catch(err => {
    // 处理异常情况
  })
现在我们要把它改造成受限制的网络请求,假设请求上限设为10个,并起名叫limitRequest.js。实现如下:
const LimitPromise = require('limit-promise')
const request = require('./request')
// 请求上限
const MAX = 10
// 核心控制器
const limitP = new LimitPromise(MAX)
// 利用核心控制器包装request中的函数
function get (url, params) {
  return limitP.call(request.get, url, params)
}
function post (url, params) {
  return limitP.call(request.post, url, params)
}
// 导出
module.exports = {get, post}
这里就完成受限请求模块的构建了,是不是很简单,而且调用接口完全没变,只需要引入limitRequest.js替代原先的即可。
参考自
使用 Promise 实现任务队列发送请求,实现最大请求数目限制的更多相关文章
- nodejs typescript怎么发送get、post请求,如何获取网易云通信token
		nodejs typescript怎么发送get.post请求,如何获取网易云通信token yarn add jshashesyarn add superagent检查语法yarn lint==== ... 
- [转]利用URLConnection来发送POST和GET请求
		URL的openConnection()方法将返回一个URLConnection对象,该对象表示应用程序和 URL 之间的通信链接.程序可以通过URLConnection实例向该URL发送请求.读取U ... 
- 使用httpclient发送get或post请求
		HttpClient 是 Apache Jakarta Common 下的子项目,可以用来提供高效的.最新的.功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建 ... 
- 在C#用HttpWebRequest中发送GET/HTTP/HTTPS请求
		通用辅助类 下面是我编写的一个辅助类,在这个类中采用了HttpWebRequest中发送GET/HTTP/HTTPS请求,因为有的时候需 要获取认证信息(如Cookie),所以返回的是HttpWeb ... 
- (转) 在C#用HttpWebRequest中发送GET/HTTP/HTTPS请求
		转自:http://blog.csdn.net/zhoufoxcn/article/details/6404236 通用辅助类 下面是我编写的一个辅助类,在这个类中采用了HttpWebRequest中 ... 
- iOS开发网络篇—发送GET和POST请求(使用NSURLSession)
		iOS开发网络篇—发送GET和POST请求(使用NSURLSession) 说明: 1)该文主要介绍如何使用NSURLSession来发送GET请求和POST请求 2)本文将不再讲解NSURLConn ... 
- Ajax详解及其案例分析------如何获得Ajax对象,使用Ajax对象发送GET和POST请求,校验用户名,POST和GET请求时的乱码处理,实现级联的下拉列表
		本节主要内容预览: 1 获得Ajax对象 2 使用Ajax对象发送GET请求 3 使用Ajax对象发送POST请求 4 使用Ajax校验用户名 5 POST请求时的乱码处理 6 GET请求时的乱码处理 ... 
- php 利用socket发送GET,POST请求
		作为php程序员一定会接触http协议,也只有深入了解http协议,编程水平才会更进一步.最近我一直在学习php的关于http的编程,许多东西恍然大悟,受益匪浅.希望分享给大家.本文需要有一定http ... 
- 【转】在C#用HttpWebRequest中发送GET/HTTP/HTTPS请求
		http://zhoufoxcn.blog.51cto.com/792419/561934 这个需求来自于我最近练手的一个项目,在项目中我需要将一些自己发表的和收藏整理的网文集中到一个地方存放,如果全 ... 
随机推荐
- java Struts 多种表单写法
			1.html:form(struts标签) 缺点:必须指定一个有效的action属性. 优点:可以使用struts token机制. 调用方法通过submit的name属性. <table al ... 
- 后端排序时去掉element表格排序的null状态
			经常会遇到远程排序,需要去掉null状态的排序,当设置sortable='custom'时,设置sort-orders为['ascending', 'descending']是不生效的.然后查到了一种 ... 
- CVT1100 错误的修复  2009-10-12 11:38
			我们在用VS2005编译MFC工程时极少会出现如下错误: 一,CVTRES : fatal error CVT1100: 重复的资源.type:MANIFEST, name:1, language:0 ... 
- AVL树旋转
			什么是AVL树? AVL树是带有平衡条件的二叉查找树,一颗AVL树首先是二叉查收树(每个节点如果有左子树或右子树,那么左子树中数据小于该节点数据,右子树数据大于该节点数据),其次,AVL树必须满足平衡 ... 
- linux驱动之内核多线程(二)
			本文摘自http://www.cnblogs.com/zhuyp1015/archive/2012/06/11/2545702.html 内核多线程是在项目中使用到,自己也不熟悉,遇到一个很囧的问题, ... 
- linux驱动之模块化驱动Makefile
			本文摘自http://blog.csdn.net/lufeiop02/article/details/6446343 Linux驱动一般以模块module的形式来加载,首先需要把驱动编译成模块的形式. ... 
- StructuredStreaming编程模型
			StructuredStreaming编程模型 基本概念 ◆ Time ◆ Trigger ◆ Input ◆ Query ◆ Result ◆ Output 案例模型:实时处理流单词统计编程模型 ... 
- Java中实现对集合中对象按中文首字母排序
			有一个person对象如下: public class Person { private String id;private String nam; } 一个list集合如下: List<Emp ... 
- 第4篇 Scrum 冲刺博客
			1.站立会议 照骗 进度 成员 昨日完成任务 今日计划任务 遇到的困难 钟智锋 重新设计项目执行流程 实现技能 庄诗楷 游戏窗口的制作 制作了开始游戏的界面,感觉还不错 无 易德康 完成所有棋子的移动 ... 
- Linux磁盘分区、挂载、查看文件大小
			快速查看系统文件大小命令 du -ah --max-depth=1 后面可以添加文件目录 ,如果不添加默认当前目录. 下面进入正题~~ 磁盘分区.挂载 引言: ①.分区的方式 a)mbr分区: 最多支 ... 
