并发请求数量过大,会在短时间内发送大量的网络请求,并且占用大量的系统资源,可能会造成接口阻塞,浏览器卡死现象。怎么才能降低并发请求数量呢?
一、并发控制核心逻辑
==========
1、创建一个ListPromise
类
类主要为了限制同时执行的任务数量来控制并发量
代码语言:javascript复制class ListPromise {
}
2、constructor
构造函数接受一个参数max
,用以设置最大并发数,并初始化了一些属性
- _max:最大并发数
- _count:当前任务执行数
- _taskQueue:任务队列
- instance:当前类实例
class ListPromise {
constructor(max) {
this._max = max;
this._count = 0
this._taskQueue = [];
// 当前实例
this.instance = null;
}
}
3、run
主入口。添加任务到队列并返回Promise
,接受一个参数caller
,用于执行异步任务。
- 通过
_createTask
创建一个任务,并判断当前任务数是否超过最大并发数
* 超过:把任务放入到任务队列
* 没超过:执行任务,调用task()返回
代码语言:javascript复制 run(caller) {
// 主入口
// 输入:外部添加的请求
// 输出:队列中的任务队列
return new Promise((resolve, reject) => {
// 创建处理任务
const task = this._createTask(caller, resolve, reject)
// 当前任务数量是否达到上限
if (this._count >= this._max) {
this._taskQueue.push(task)
} else {
task()
}
})
}
4、_createTask
创建任务,返回一个任务函数,这就可以理解为什么在run
中通过this._createTask
创建的任务可以直接调用。 任务函数会执行caller
函数,根据结果去调用reslove()
或者reject
。 在直接结束时当前任务数减1,通过this._taskQueue.length
判断当前队列中是否还有待执行的任务。如果有则取出并执行。
_createTask(caller, resolve, reject) {
return () => {
caller().then(res => {
resolve(res)
}).catch(err => {
reject(err)
}).finally(() => {
this._count--;
if (this._taskQueue.length) {
const task = this._taskQueue.shift();
task()
}
})
this._count ;
}
}
5、获取ListPromise
单例实例
如果当前实例不存在,则生成一个实例,否则返回当前实例。
代码语言:javascript复制static getInstance(max) {
if (!this.instance) {
this.instance = new ListPromise(max)
}
return this.instance;
}
6、ListPromise
核心代码
class ListPromise {
constructor(max) {
this._max = max;
this._count = 0
this._taskQueue = [];
// 当前实例
this.instance = null;
}
run(caller) {
// 主入口
// 输入:外部添加的请求
// 输出:队列中的任务队列
return new Promise((resolve, reject) => {
// 创建处理任务
const task = this._createTask(caller, resolve, reject)
// 当前任务数量是否达到上限
if (this._count >= this._max) {
this._taskQueue.push(task)
} else {
task()
}
})
}
_createTask(caller, resolve, reject) {
return () => {
caller().then(res => {
resolve(res)
}).catch(err => {
reject(err)
}).finally(() => {
this._count--;
if (this._taskQueue.length) {
const task = this._taskQueue.shift();
task()
}
})
this._count ;
}
}
static getInstance(max) {
if (!this.instance) {
this.instance = new ListPromise(max)
}
return this.instance;
}
}
二、具体使用
======
1、创建一个ListPromise
实例,并设置最大并发量
const listPromise = ListPromise.getInstance(2); // 设置最大并发数为 2
2、模拟异步操作
通过setTimeout
模拟一个异步任务,并且声明testFunction
返回一个Promise
function delay(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
function testFunction() {
return delay(1000); // 模拟一个异步函数
}
3、添加任务队列
通过listPromise.run(testFunction)
添加到任务队列中,testFunction
是一个异步函数,返回值是Promise,可以通过then
以及catch
处理成功和失败时的回调。
4、具体使用时核心代码
代码语言:javascript复制 // 示例用法
const listPromise = ListPromise.getInstance(2); // 设置最大并发数为 2
function delay(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
function testFunction() {
return delay(1000); // 模拟一个异步函数
}
listPromise.run(testFunction)
.then(() => console.log('Task 1 completed'))
.catch((err) => console.error('Task 1 failed:', err));
listPromise.run(testFunction)
.then(() => console.log('Task 2 completed'))
.catch((err) => console.error('Task 2 failed:', err));
listPromise.run(testFunction)
.then(() => console.log('Task 3 completed'))
.catch((err) => console.error('Task 3 failed:', err));
listPromise.run(testFunction)
.then(() => console.log('Task 4 completed'))
.catch((err) => console.error('Task 4 failed:', err));
listPromise.run(testFunction)
.then(() => console.log('Task 5 completed'))
.catch((err) => console.error('Task 5 failed:', err));
listPromise.run(testFunction)
.then(() => console.log('Task 6 completed'))
.catch((err) => console.error('Task 6 failed:', err));
listPromise.run(testFunction)
.then(() => console.log('Task 7 completed'))
.catch((err) => console.error('Task 7 failed:', err));
listPromise.run(testFunction)
.then(() => console.log('Task 8 completed'))
.catch((err) => console.error('Task 8 failed:', err));
三、源码
====
代码语言:javascript复制 class ListPromise {
constructor(max) {
this._max = max;
this._count = 0
this._taskQueue = [];
// 当前实例
this.instance = null;
}
run(caller) {
// 主入口
// 输入:外部添加的请求
// 输出:队列中的任务队列
return new Promise((resolve, reject) => {
// 创建处理任务
const task = this._createTask(caller, resolve, reject)
// 当前任务数量是否达到上限
if (this._count >= this._max) {
this._taskQueue.push(task)
} else {
task()
}
})
}
_createTask(caller, resolve, reject) {
return () => {
caller().then(res => {
resolve(res)
}).catch(err => {
reject(err)
}).finally(() => {
this._count--;
if (this._taskQueue.length) {
const task = this._taskQueue.shift();
task()
}
})
this._count ;
}
}
static getInstance(max) {
if (!this.instance) {
this.instance = new ListPromise(max)
}
return this.instance;
}
}
// 示例用法
const listPromise = ListPromise.getInstance(2); // 设置最大并发数为 2
function delay(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
function testFunction() {
return delay(1000); // 模拟一个异步函数
}
listPromise.run(testFunction)
.then(() => console.log('Task 1 completed'))
.catch((err) => console.error('Task 1 failed:', err));
listPromise.run(testFunction)
.then(() => console.log('Task 2 completed'))
.catch((err) => console.error('Task 2 failed:', err));
listPromise.run(testFunction)
.then(() => console.log('Task 3 completed'))
.catch((err) => console.error('Task 3 failed:', err));
listPromise.run(testFunction)
.then(() => console.log('Task 4 completed'))
.catch((err) => console.error('Task 4 failed:', err));
listPromise.run(testFunction)
.then(() => console.log('Task 5 completed'))
.catch((err) => console.error('Task 5 failed:', err));
listPromise.run(testFunction)
.then(() => console.log('Task 6 completed'))
.catch((err) => console.error('Task 6 failed:', err));
listPromise.run(testFunction)
.then(() => console.log('Task 7 completed'))
.catch((err) => console.error('Task 7 failed:', err));
listPromise.run(testFunction)
.then(() => console.log('Task 8 completed'))
.catch((err) => console.error('Task 8 failed:', err));
我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!