如何实现 Promise 池

一、背景

最近在写一个批量上传的 node 脚本,其实大家可以想到批量上传带来的接口性能问题,如果将需要上传的文件通过多个异步请求同时上传的话,服务器方面应该是吃不消的,所以这里提出一个 promise 池的概念。

其原理就是固定每次运行的 promise 函数个数,其中有一个完成之后再继续再向这个池子中新增一个 promise 函数运行,这样就可以保持一直有固定个数的 promise 函数在运行,并且服务端的压力不会太大。

二、实现

具体的实现就像是接力跑步,比如我们规定最多同时执行 5 个异步函数。

赛道上只能有 5 个运动员在跑步,但是要让所有的运动员都跑一次,最好的方法就是 5 个运动员分别在 5 个赛道上跑,谁先跑到终点就将接力棒传递给下一个运动员,这样就能使每个运动员跑一次并且赛道上最多有 5 个运动员。

当然,这里只是说跑到终点会将接力棒传给下一个运动员,但是如果一个运行员跑步过程中受伤了,不能继续完成跑步的话就要放弃,并将接力棒传递给下一个运动员,也就是 promise 函数中的 reject。

还有一个点就是如何监听所有的 promise 函数已经结束,我们在每个 promise 函数运行结束之后都要运行判断一下当前正在执行的函数个数以及还没有运行的函数个数是否为 0,为 0 的话则表示函数运行结束。这里我们使用 EventEmitter 来发送结束消息,表示所有 promise 函数已经执行完成。

具体的实现代码如下:

class PromisePool extends EventEmitter {
  constructor(params,fn,max) {
    super();
    this.params = params; // 异步函数的参数数组
    this.fn = fn; // 异步函数
    this.max = max; // 同时运行的最大数量
    this.pool = []; // 存放task
    this.successNum = 0; // 成功个数
    this.failNum = 0; // 失败个数
    this.count = params.length; // 当前正在运行的异步函数个数
    this.init();
  }
  // 初始化函数
  init() {
    while (this.count < this.max) {
      const param = this.params.shift();
      if(!param){ break; }
      this.genTask(param);
    }
  }
  genTask(param) {
    this.count++;
    const task = this.fn(param);
    task.then(() => {
      this.successNum++;
    }).catch(() => {
      this.failNum++;
    }).finally(() => {
      this.count--;
      this.init();
      if(this.count === 0 && this.params.length === 0){
        this.emit('finish');
      }
    })
  }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


kindeditor4.x代码高亮功能默认使用的是prettify插件,prettify是Google提供的一款源代码语法高亮着色器,它提供一种简单的形式来着色HTML页面上的程序代码,实现方式如下: 首先在编辑器里面插入javascript代码: 确定后会在编辑器插入这样的代码: <pre
这一篇我将介绍如何让kindeditor4.x整合SyntaxHighlighter代码高亮,因为SyntaxHighlighter的应用非常广泛,所以将kindeditor默认的prettify替换为SyntaxHighlighter代码高亮插件 上一篇“让kindeditor显示高亮代码”中已经
js如何实现弹出form提交表单?(图文+视频)
js怎么获取复选框选中的值
js如何实现倒计时跳转页面
如何用js控制图片放大缩小
JS怎么获取当前时间戳
JS如何判断对象是否为数组
JS怎么获取图片当前宽高
JS对象如何转为json格式字符串
JS怎么获取图片原始宽高
怎么在click事件中调用多个js函数
js如何往数组中添加新元素
js如何拆分字符串
JS怎么对数组内元素进行求和
JS如何判断屏幕大小
js怎么解析json数据
js如何实时获取浏览器窗口大小
原生JS实现别踩白块小游戏(五)
原生JS实现别踩白块小游戏(一)