题目
function timeout(fn, time) {
return () => {
return new Promise((resolve) => {
setTimeout(() => {
fn();
resolve();
}, time);
});
};
}
task.add(
timeout(() => {
console.log("任务一");
}, 1000)
); // 1000毫秒后输出'任务一'
task.add(
timeout(() => {
console.log("任务二");
}, 2000)
); // 2000毫秒后输出'任务二'
task.add(
timeout(() => {
console.log("任务三");
}, 2000)
); // 3000毫秒后输出'任务三'
task.add(
timeout(() => {
console.log("任务四");
}, 3000)
); // 5000毫秒后输出'任务四'
分析
- 1.任务一和任务二是按照时间顺序执行的;
- 2.任务三延迟了一秒执行,任务四延迟了两秒执行;
- 3.根据时间推算发现任务三是在任务一执行完毕后执行,刚好结束时是第三秒;
- 4.根据时间推算发现任务四是任务二执行完毕后,任务四开始执行刚好结束时是第五秒
- 5.可以知道任务一和任务二同步执行,任务三和任务四是在前面任务执行完毕后,按顺序补位继续执行的结果。
- 6.总结上面可以知道,其实就是考察 Promise 的并行执行,上面的并行数量是 2;
实现步骤
1.创建一个类,要有最大并发数,存储任务的数组
class Task {
constructor(limit) {
this.limit = limit; // 最大并发数
this.queue = []; // 任务存储队列
}
}
2.要有 add 方法能够不断添加任务函数
class Task {
constructor(limit) {
this.limit = limit; // 最大并发数
this.queue = []; // 任务存储队列
}
add(promise) {
this.queue.push(promise);
}
}
3.添加任务以后,要立刻执行给定任务,并检查“当前并发数”是否大于“最大并发数”,保证同时只能执行limit任务函数;同时当前任务队列的数量要大于0,保证不会导致意外出错
class Task {
constructor(limit) {
this.limit = limit; // 最大并发数
this.queue = []; // 任务存储队列
this.parallel = 0; // 当前并发数
}
add(promise) {
this.queue.push(promise);
this._run();
}
_run() {
if (this.queue.length > 0 && this.parallel < this.limit) {
const first = this.queue.shift();
first()
this.parallel += 1;
}
}
}
4.在第3步只是保证了有任务函数就立刻按照最大并发数执行;但是超过并发数的任务并没有执行;所以需要在任务函数执行完毕后,无论成功还是失败都要执行一次_run函数,并且把“当前并发数”减一
class Task {
constructor(limit) {
this.limit = limit; // 最大并发数
this.queue = []; // 任务存储队列
this.parallel = 0; // 当前并发数
}
add(promise) {
this.queue.push(promise);
this._run();
}
_run() {
if (this.queue.length > 0 && this.parallel < this.limit) {
const first = this.queue.shift();
first().finally(() => {
this.parallel -= 1;
this._run();
});
this.parallel += 1;
}
}
}
const task = new Task(2);
测试结果
function timeout(fn, time) {
return () => {
return new Promise((resolve) => {
setTimeout(() => {
fn();
resolve();
}, time);
});
};
}
class Task {
constructor(limit) {
this.limit = limit; // 最大并发数
this.queue = []; // 任务存储队列
this.parallel = 0; // 当前并发数
}
add(promise) {
this.queue.push(promise);
this._run();
}
_run() {
if (this.queue.length > 0 && this.parallel < this.limit) {
const first = this.queue.shift();
first().finally(() => {
this.parallel -= 1;
this._run();
});
this.parallel += 1;
}
}
}
const task = new Task(2);
task.add(
timeout(() => {
console.log("任务一");
}, 1000)
); // 1000毫秒后输出'任务一'
task.add(
timeout(() => {
console.log("任务二");
}, 2000)
); // 2000毫秒后输出'任务二'
task.add(
timeout(() => {
console.log("任务三");
}, 2000)
); // 3000毫秒后输出'任务三'
task.add(
timeout(() => {
console.log("任务四");
}, 3000)
); // 5000毫秒后输出'任务四'