【若川视野 x 源码共读】第31期 | p-limit 限制并发数

302 阅读2分钟

本文参加了由公众号@若川视野 发起的每周源码共读活动,点击了解详情一起参与。

p-limit处理的问题

引用p-limit文档中的一句话:

Run multiple promise-returning & async functions with limited concurrency.(在限制并发数情况下并发执行多个异步函数) 这里我们简单了解下几个知识点:

  • 并发:通俗来说就是指一个时间段中有几个任务都处于已启动运行到运行完毕之间,且这几个任务都是在同一个线程上运行,但任一个时刻点上只有一个任务在线程上运行。
  • 高并发带来的问题
    • 服务端:过高的并发量将导致服务有性能问题甚至服务器奔溃
    • 客户端:过高的并发会导致客户端其他任务执行延迟,体验不佳。 而p-limit就是通过限制并发数来避免高并发所带来的问题。

本文可以学到什么

  • p-limit使用及其流程
  • 可控并发的实现

p-limit使用及其流程

  • 安装:npm install p-limit
  • 使用
    import pLimit from 'p-limit';
    const limit = pLimit(1);
    const input = [
            limit(() => fetchSomething('foo')),
            limit(() => fetchSomething('bar')),
            limit(() => doSomething())
    ];
    // Only one promise is run at once
    const result = await Promise.all(input);
    console.log(result);
  • 执行流程

image.png

可控并发的实现

可控并发实现主要包括几个部分:数据结构选型、并发数控制、任务执行后能够继续执行下一个任务。

数据结构

由于任务具有先进先出的性质,故存储任务的数据结构应首选队列image.png p-limit这里存储任务用的是yocto-queue;对应的源码解读yocto-queue源码解读

image.png

并发数控制

那怎么控制并发数?
这里可以借助p-limit中的实现,即借助变量activeCount来统计当前并发数,超出部分不立刻执行。

image.png

上面await Promise.resolve()是等待直到下一个微任务开始前,才进行if判断来控制并发。
这里有点复杂,我们通过demo来验证:

image.png

任务完毕后执行下一个任务

上述数据结构和并发数控制已经完成后,那我们怎么告诉任务执行完继续执行任务呢?
诶,p-limit里面通过给任务包装一层,让其执行完继续执行队列里的下一个任务

image.png
由于前面已经进行了并发数限制,故后面任务执行完只需执行next即可,即当前并发数 <= 最大并发数

image.png

总结

通过学习p-limit源码,可以学习到简单的并发控制实现、p-limit的使用及其处理的问题。