设计一个异步队列-JS实现
330数据结构kohai
实现结果
// 创建一个队列实例
const queue = AsyncQueue.create();
// 定义一个睡眠函数
const sleep = (t) => new Promise((r) => setTimeout(r, t));
// 往队列中添加一个异步方法,方法内部睡眠了 1s,1s 后打印并返回结果,
// push 方法返回一个 promise 实例,值为异步方法的返回值。
queue.push(async () => {
await sleep(1000);
console.log('1s ', new Date());
return [1, new Date()];
}).then(console.log);
// 添加的异步方法内部出现异常,也会通过 push 方法抛出来,
// 通过 catch 可以进行捕获,该异常只会终止当前任务,对后续的任务不会有影响。
queue.push(async () => {
await sleep(1000);
console.log('2s ', new Date());
if (new Date().getFullYear() === 2021) {
throw new Error('Current year is 2021');
}
return [2, new Date()];
}).then(console.log).catch(console.error);
queue.push(async () => {
await sleep(1000);
console.log('3s ', new Date());
return [3, new Date()];
}).then(console.log);
js复制代码
实现
class AsyncQueue {
static create(name) {
return new this(name);
}
constructor(name) {
this.name = name;
// 任务队列
this.queue = [];
// 是否有任务正常执行
this.running = false;
}
push(fun) {
return new Promise((resovle, reject) => {
// 将 fun 包装一层放进任务队列中
this.queue.push(async () => {
this.running = true;
try {
const res = await fun();
resovle(res);
} catch(e) {
reject(e);
}
this.running = false;
// 获取下一个任务并执行
const next = this.queue.shift();
next?.();
});
// 若当前未有任务执行中,则触发队列的执行
if (!this.running) {
this.queue.shift()?.();
}
});
}
}
js复制代码