任务队列
队列的特点就是先进先出
先开始的任务执行完后,才能开始执行后续任务
另外任务队列中有任务时是自动执行的。
另外提一点,实现稍微复杂一点功能,全都是闭包!!
设计:new一个队列,返回值是一个function,这个function的入参为为task(类型promise),返回值也是promise
const queue = new Queue();
queue(task1).then(data=>console.log(data));
queue(task2).then(data=>console.log(data));
//始终都是task1的结果先输出
- 实现一个先进先出的普通队列
class Queue {
constructor() {
let waitingQueue = [];
let isRunning = false;//记录是否有未完成的任务
function execute(task, resolve, reject) {
task()
.then((data) => {
resolve(data);
})
.catch((e) => {
reject(e);
})
.finally(() => {
//等待任务队列中如果有任务,则触发它;否则设置isRunning = false,表示无任务状态
if (waitingQueue.length) {
const next = waitingQueue.shift();
execute(next.task, next.resolve, next.reject);
} else {
isRunning = false;
}
});
}
return function(task) {
return new Promise((resolve, reject) => {
if (isRunning) {
waitingQueue.push({
task, resolve, reject });
} else {
isRunning = true;
execute(task, resolve, reject);
}
});
};
}
}
const queue = new Queue();
const task1 = () =>
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('task1');
}, 3000);
});
const task2 = () =>
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('task2');
}, 1000);
});
const queue = new Queue();
queue(task1).then((data) => console.log(data));
queue(task2).then((data) => console.log(data));
//result
//task1
//task2
2.实现一个有时间间隔,并且超时后会中断任务的任务队列
有几个要点:超时后终止当前任务直接开始下一个任务;delay时间后才会执行下一个任务;如果任务delay了但没超时,则需要立即执行下一个任务
class Queue {
constructor({
delay, timeout }) {
let timer = null;//当有任务执行时,设置超时检测的定时器
let waitingQueue = [];//等待任务的队列
function execute(task, resolve, reject) {
let resolved = false;//记录任务是否结束
let executeNext = false;//记录是否任务结束后,立即执行下一个任务
task().then((data) => {
//任务未超时,则会进入这里
resolve(data);
resolved = true;//标记任务完成
clearTimeout(timer);//清除超时计时器
timer = null;
if (executeNext) {
//true代表任务是在delay后完成的,所以直接执行下一个任务
const next = waitingQueue.shift();
if (next) {
execute(next.task, next.resolve, next.reject);
}
}
});
timer = setTimeout(() => {
reject('超时');//超时直接调用reject
timer = null;
const next = waitingQueue.shift();
if (next) {
//立即执行下一个任务
execute(next.task, next.resolve, next.reject);
}
}, timeout);
//delay时间后,自动执行下一个任务
setTimeout(() => {
if (resolved) {
//true代表上一个任务已经完成,可以直接执行下一个任务
const next = waitingQueue.shift();
if (next) {
execute(next.task, next.resolve, next.reject);
}
}
executeNext = true;//标记当前任务完成后,立即执行下个任务(给任务在delay之后完成用)
}, delay);
}
return function(task) {
return new Promise((resolve, reject) => {
if (!timer) {
//没有任务,则直接执行
execute(task, resolve, reject);
} else {
//否则 将任务放入等待队列中
waitingQueue.push({
task, resolve, reject });
}
});
};
}
}
const task1 = () =>
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('task1');
}, 3000);
});
const task2 = () =>
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('task2');
}, 2000);
});
const task3 = () =>
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('task3');
}, 1000);
});
const queue = new Queue({
delay:2000,timeout:3000});
queue(task1).then((data) => console.log(data));
queue(task2).then((data) => console.log(data));
queue(task3).then((data) => console.log(data));
//task1
//task2
//task3
const task4 = () =>
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('task4');
}, 4000);
});
queue(task4).then((data) => console.log(data));
queue(task1).then((data) => console.log(data));
queue(task2).then((data) => console.log(data));
queue(task3).then((data) => console.log(data));
//Uncaught (in promise) 超时
//task1
//task2
//task3