更多文章可看专栏:juejin.cn/column/7423…
multiRequest并发请求
function multiRequest(urls = [], maxNum) {
// 请求总数量
const len = urls.length;
// 根据请求数量创建一个数组来保存请求的结果
const result = new Array(len).fill(false);
// 当前完成的数量
let count = 0;
return new Promise((resolve, reject) => {
// 请求maxNum个
while (count < maxNum) {
next();
}
function next() {
let current = count++;
// 处理边界条件
if (current >= len) {
// 请求全部完成就将promise置为成功状态, 然后将result作为promise值返回
!result.includes(false) && resolve(result);
return;
}
const url = urls[current];
console.log(`开始 ${current}`, new Date().toLocaleString());
fetch(url)
.then((res) => {
// 保存请求结果
result[current] = res;
console.log(`完成 ${current}`, new Date().toLocaleString());
})
.catch((err) => {
console.log(`结束 ${current}`, new Date().toLocaleString());
result[current] = err;
})
.finally(() => {
// 请求没有全部完成, 就递归
if (current < len) {
next();
}
});
}
});
}
Scheduler异步调度
/**
* 题目: JS实现一个带并发限制的异步调度器Scheduler,保证同时运行的任务最多有两个。完善代码中Scheduler类,使得以下程序能正确输出
* 条件: 只能修改Sheduler
**/
class Scheduler {
constructor() {
this.max = 2;
this.cache = [];
this.task = [];
}
add(promiseCreator) {
return new Promise((resolve) => {
promiseCreator.resolve = resolve;
if (this.task.length < this.max) {
this.runTask(promiseCreator);
} else {
this.cache.push(promiseCreator);
}
})
}
runTask(promiseCreator) {
this.task.push(promiseCreator);
promiseCreator().then(() => {
promiseCreator.resolve(); //promiseCreator异步任务完成以后,再调用外层Promise的resolve以便add().then()的执行
var index = this.task.indexOf(promiseCreator);
this.task.splice(index, 1); //从正在进行的任务队列中删除
if (this.cache.length > 0) {
this.runTask(this.cache.shift());
}
})
}
}
const timeout = (time) => new Promise(resolve => {
setTimeout(resolve, time);
})
const scheduler = new Scheduler();
const addTask = (time, order) => {
scheduler
.add(() => timeout(time))
.then(() => console.log(order));
}
addTask(1000, '1')
addTask(500, '2')
addTask(300, '3')
addTask(400, '4')// output: 2 3 1 4
// 一开始,1、2两个任务进入队列
// 500ms时,2完成,输出2,任务3进队
// 800ms时,3完成,输出3,任务4进队
// 1000ms时,1完成,输出1
// 1200ms时,4完成,输出4
LazyMan懒汉模型
class LazyMan {
tasks = []; // 任务列表
name = ""; // 懒汉
constructor(name) {
this.name = name;
// 采用异步,确保所有的链式调用函数都添加到列表中后,自动执行第一个任务
setTimeout(() => {
this.next();
}, 0);
}
// 执行下一个任务,每次执行完都会从任务列表中删除
next() {
const task = this.tasks.shift(); // 从头部删除,会直接影响原数组
task && task();
}
// 阻塞,使得程序延后time执行
sleep(time) {
// 定义一个任务函数
const task = () => {
console.log(`sleep ${time}s 开始`);
setTimeout(() => {
console.log(`sleep ${time}s 结束`);
this.next(); // 执行完当前函数后,继续执行下一个任务,直到任务执行完毕
}, time * 1000); // 使用定时器来模拟实现阻塞功能
};
// 添加到任务列表中
this.tasks.push(task);
// 返回当前对象,保持链式调用
return this;
}
eat(food) {
// 定义一个任务函数
const task = () => {
console.log(`eat ${food}`);
this.next(); // 执行完当前函数后,继续执行下一个任务,直到任务执行完毕
};
// 添加到任务列表中
this.tasks.push(task);
// 返回当前对象,保持链式调用
return this;
}
done() {
const task = () => {
// console.log(`当前待处理的任务:`);
// console.log(`${this.tasks}`);
this.next();
};
this.tasks.unshift(task);
return this;
}
}
const lazyMan = new LazyMan("张三");
lazyMan.eat("dinner").sleep(10).eat("super").sleep(5);