引言
假设有这么一个场景:
- 前端订阅后台数据的变化,如果发生变化,则触发订阅回调;
- 回调函数中,会执行一些耗时操作,如:请求接口,发送短信,存历史数据等;
- 要求以上所有的操作都必须按照订阅触发的顺序执行;
我们都知道,回调本身就是一种异步操作,我们仅仅依靠订阅回调无法保证回调中任务执行顺序的。
为了解决这个问题,我们可以使用任务队列,将回调函数添加到任务队列中,然后按照顺序依次执行。
任务队列的概念
顾名思义,任务队列就是存放任务的队列,队列中的任务都严格按照进入队列的先后顺序执行。
在前一条任务执行完毕后,立即执行下一条任务,直到任务队列清空。
任务队列的基本执行流程如下:
- 给任务队列添加任务,并判断执行标识;
- 如果执行标识为 false,则将任务从队列中独立出来;
- 开始执行任务,将执行标识置为 true;
- 执行完毕后,判断队列是否为空,如果不为空,则继续执行下一条任务;
- 直至任务队列清空。
任务队列一直在循环进行如上步骤。
任务队列的 JS 实现
我们选择使用数组来维护队列的执行顺序,按照“先进先出“的原则,依次从数组的第一个元素开始往后执行。
简易代码实现如下:
/** @format */
class TaskQueue {
constructor() {
this.queue = [];
this.isRunning = false;
}
/**
* @description 将任务添加至队列
* @param {Promise} queueFunction
* @returns {undefined}
*/
addQueue(queueFunction) {
this.queue.push(queueFunction);
if (!this.isRunning) {
this.processQueue();
}
}
/**
* @description 如果队列不为空,则开始处理队列中的任务,本次任务执行完毕后,立刻开始下一条任务的执行
* @param {}
*/
processQueue() {
if (this.queue.length > 0) {
this.isRunning = true;
const queueFunction = this.queue.shift();
queueFunction().finally(() => {
this.processQueue();
});
} else {
this.isRunning = false;
}
}
}
测试
我们使用如下代码来测试上述实现:
let taskQueue = new TaskQueue();
let f1 = function (name) {
return new Promise((resolve) => {
setTimeout(() => {
console.log(`我是 f1`, name);
resolve();
}, 3000);
});
};
let f11 = async function () {
await f1(" 任务 1");
};
let f2 = function (name) {
return new Promise((resolve) => {
setTimeout(() => {
console.log(`我是 f2`, name);
resolve();
}, 2000);
});
};
let f22 = async function () {
await f2(" 任务 2");
};
let f3 = function (name) {
return new Promise((resolve) => {
setTimeout(() => {
console.log(`我是 f3`, name);
resolve();
}, 1000);
});
};
let f33 = async function () {
await f3(" 任务 3");
};
taskQueue.addQueue(f11);
taskQueue.addQueue(f22);
taskQueue.addQueue(f33);
// 依次输出:
// 我是 f1 任务 1
// 我是 f2 任务 2
// 我是 f3 任务 3
如果不使用任务队列,上面的测试应该是按照 f1 -> f2 -> f3 的顺序执行,但是使用了任务队列之后,f1 -> f2 -> f3 的顺序执行被改变了,这是因为任务队列的执行顺序是按照添加的顺序来的,而不是按照执行顺序来的。
总结
任务队列的实现非常简单,但是使用起来却非常灵活,我们可以根据实际需求来决定任务队列的执行顺序,也可以根据实际需求来决定任务队列的执行时机。
本文算是抛砖引玉,介绍了简洁版的任务队列实现,如果大家有更好的想法和建议,都可以在评论区留言,一起讨论。
~
~ 本文完,感谢阅读!
~
标签:顺序,队列,JS,任务,resolve,let,执行 From: https://blog.51cto.com/bianchengsanmei/7558210