核心

  • 设置最大请求数量,当前请求数量,待执行队列
  • 调用时,创建一个新任务,然后判断是否达到最大请求数量,若达到则将任务追加到待执行队列,否则,则直接执行该任务。并返回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替代原先的即可。

参考自

https://www.jianshu.com/p/cc706239c7ef

最新文章

  1. swift相关
  2. YUV420查表法高效、无失真的转换为RGB32格式
  3. 用Docker封装一个web应用(Django)
  4. C语言 线性表 双向链式结构 实现
  5. get与post
  6. RARP
  7. 让IE支持Css3属性(圆角、阴影、渐变)
  8. java入门时的一些基本概念的理解(j2ee,j2se,j2me,jdk,sdk,jre,jvm,跨平台)
  9. java第二天
  10. Supervisor使用(启动nginx/tomcat/redis)
  11. Asp.net core中实现自动更新的Option
  12. ionic cordova platform add android Cordova failed to install plugin Error: ENOENT: no such file or directory AndroidManifest.xml
  13. qml:: QVariant转为自定义类型
  14. with文件操作
  15. Process 开启子进程 的两种方式、join控制子进程、守护进程
  16. java基础 逻辑
  17. Vue3.0项目快速搭建
  18. 双缓冲队列解决WPF界面卡死
  19. Serializable java序列化
  20. 导入tensorflow:ImportError: libcublas.so.9.0: cannot open shared object file: No such file or director【转】

热门文章

  1. JavaScript重定向
  2. MySQL数据库——数据约束
  3. Linux用户锁定、解锁及锁定查看
  4. 使用halo搭建自己的博客并配置https域名访问
  5. 水题大战Vol.3 B. DP搬运工2
  6. 用python进行实际地址经纬度提取
  7. 幂次方的四种快速取法(不使用pow函数)
  8. 编译原理根据项目集规范族构造LR(0)分析表
  9. Java实现树形结构的数据转Json格式
  10. 求求大厂给个Offer:Map面试题