【源码学习】第20期 | 性能篇:前端如何控制并发数?
- 本文参加了由公众号@若川视野 发起的每周源码共读活动,点击了解详情一起参与。
- 第31期 | p-limit 限制并发数
前言
开始学习之前,先来说说并发数,并发数是指系统同时能处理的请求数量,聪明的童鞋可能就能联想到性能优化了!常用于控制并发数的npm包是p-limit
,接下来就来学习探讨一下~
收获清单
- p-limit 的使用场景
- p-limit 的源码分析
p-limit简介及应用
p-limit 的官方介绍是以有限的并发性运行多个承诺返回和异步函数,也就是控制并发数,其实应用场景还蛮多的,例如批量操作,大批量并发请求会造成接口阻塞造成等待时间过长或者浏览器卡死等一系列问题,前端控制请求并发数的话就能缓解服务器的压力,自然而然就提高性能了,还有大文件分段上传也可以通过控制并发数实现,echarts多图表同时渲染等等....
用法
源码下载
git clone https://github.com/sindresorhus/p-limit
开启调试
看完使用教程就可以看package.json找到入口文件,然后看script
开启调试
源码分析
由于源码中会用到队列这个数据结构,因此先了解一下队列。队列是一个有序的元素列表,其中元素在队列的末端插入并从队列的前部删除。队列一个很重要的原则就是先进先出,举个栗子大家排队做核酸的队伍就是一个队列。
p-limit 关键源码
接着跟着调试逐步分析p-limit的实现,代码只有68行~
import Queue from 'yocto-queue';
export default function pLimit(concurrency) {
// 限制输入并发数为1至无穷大的正整数
if (!((Number.isInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency > 0)) {
throw new TypeError('Expected `concurrency` to be a number from 1 and up');
}
// 新建队列
const queue = new Queue();
let activeCount = 0;
// ...省略代码
const enqueue = (fn, resolve, args) => {
queue.enqueue(run.bind(undefined, fn, resolve, args));
(async () => {
await Promise.resolve();
if (activeCount < concurrency && queue.size > 0) {
queue.dequeue()();
}
})();
};
const generator = (fn, ...args) => new Promise(resolve => {
enqueue(fn, resolve, args);
});
// ...给generator定义新属性
return generator;
}
简单分析一下这些代码:
- p-limit的实现依赖于队列(yocto-queue)
- concurrency代表最大限制并发数,需为大于1的正整数,activeCount代表当前执行的异步函数的数量,其中activeCount要小于concurrency
- 执行一次p-limit函数会生成一个generator函数,主要利用
yocto-queue
的enqueue()
和dequeue()
实现- 入队的是经过run方法处理的异步函数
- 当activeCount小于concurrency时,activeCount减一并执行出队的函数
next&&run函数
const next = () => {
activeCount--;
if (queue.size > 0) {
queue.dequeue()();
}
};
const run = async (fn, resolve, args) => {
activeCount++;
const result = (async () => fn(...args))();
resolve(result);
try {
await result;
} catch {}
next();
};
- next 方法作用
- activeCount减一
- 当队列数量大于0,执行出队的函数
- run 方法作用
- activeCount加一
- 用异步等函数执行完
- 调用next函数
总结收获
简单总结一下p-limit:主要利用yocto-queue
的入队和出队控制并发执行的函数,在入队时用run、next方法逐步执行函数继而起到限流的作用。日常项目中也可以利用p-limit
来控制并发数,本来是周末要学的内容,愣是拖到了今天才学完,希望接下来:初心如磐,奋楫笃行!
转载自:https://juejin.cn/post/7171656026079363080