如果有20个Promise,浏览器的并发设置为3,如何保证始终有3个Promise在请求
https://segmentfault.com/a/11...
或者这也是一种:
说一下思路:
1.维护一个任务队列;
2.维护一个并发值;
3.开始的时候同时执行等于并发值的任务;
4.每个任务都是异步的,任务fulfill状态后判断队列里是否有任务&&在执行的任务是否达到并发值,满足条件从任务队列中拿出一个任务执行。
class Scheduler {
constructor(limit) {
this.queue = [];
this.limit = limit;
this.runCounts = 0;
}
add(time, task) {
const promiseProducer = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(task);
resolve();
}, time);
})
}
this.queue.push(promiseProducer)
}
request() {
if (this.queue.length && this.runCounts <= this.limit) {
this.runCounts++;
this.queue.shift()().then(() => {
this.runCounts--;
this.request();
});
}
}
start() {
for (let i = 0; i < this.limit; i++) {
this.request();
}
}
}
const scheduler = new Scheduler(2);
const addTask = (time, order) => {
scheduler.add(time, order);
};
addTask(1000, "1");
addTask(500, "2");
addTask(300, "3");
addTask(400, "4");
scheduler.start();
已参与了 SegmentFault 思否社区 10 周年「问答」打卡 ,欢迎正在阅读的你也加入。
这个人很懒,具体实现只写了20多行代码(娱乐实现,仅供参考).
// 必须先获得锁后释放锁,获得锁和释放锁的次数必须相同,
// 否则会产生未定义行为
class MyLock {
constructor(
// 可以进入临界区的最大协程数量
private N: number
) {}
// 当前被挂起的协程的队列
private queue: (() => void)[] = []
// 一个协程在进入临界区之前需要获取一把锁
async acquire() {
if (this.N > 0) {
// 还有剩余的名额,直接返回协程进入临界区,名额减1
--this.N
} else {
// 没有剩余的名额了,在这里返回一个处于pending状态的promise
// 让协程挂起,并将其放到等待队列中
return new Promise<void>((resolve) => {
this.queue.push(resolve)
})
}
}
async release() {
if (this.queue.length) {
// 当前等待队列中有等待的协程,将队列中的第一个协程resume
this.queue.shift()!()
return
}
// 没有等待的协程,将名额加1
++this.N
}
}
const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))
const tasks = [
async () => {
await delay(10000)
console.log('100')
},
async () => {
await delay(12000)
console.log('200')
},
async () => {
await delay(2300)
console.log('300')
},
async () => {
await delay(2400)
console.log('400')
},
async () => {
await delay(2500)
console.log('500')
},
async () => {
await delay(2600)
console.log('600')
},
async () => {
await delay(2700)
console.log('700')
},
]
const main = async () => {
const lock = new MyLock(3)
for (const task of tasks) {
await lock.acquire()
task().then(() => {
lock.release()
})
}
}
main()
6 回答3k 阅读✓ 已解决
8 回答4.7k 阅读✓ 已解决
6 回答3.4k 阅读✓ 已解决
5 回答2.8k 阅读✓ 已解决
6 回答2.3k 阅读
5 回答6.3k 阅读✓ 已解决
4 回答2.3k 阅读✓ 已解决
什么都不需要做吧,浏览器并发是3,那浏览器会自己处理请求队列的啊。
已参与了 SegmentFault 思否社区 10 周年「问答」打卡 ,欢迎正在阅读的你也加入。