基于JS實現(xiàn)任務(wù)隊列的示例代碼
引言
假設(shè)有這么一個場景:
- 前端訂閱后臺數(shù)據(jù)的變化,如果發(fā)生變化,則觸發(fā)訂閱回調(diào);
- 回調(diào)函數(shù)中,會執(zhí)行一些耗時操作,如:請求接口,發(fā)送短信,存歷史數(shù)據(jù)等;
- 要求以上所有的操作都必須按照訂閱觸發(fā)的順序執(zhí)行;
我們都知道,回調(diào)本身就是一種異步操作,我們僅僅依靠訂閱回調(diào)無法保證回調(diào)中任務(wù)執(zhí)行順序的。
為了解決這個問題,我們可以使用任務(wù)隊列,將回調(diào)函數(shù)添加到任務(wù)隊列中,然后按照順序依次執(zhí)行。
任務(wù)隊列的概念
顧名思義,任務(wù)隊列就是存放任務(wù)的隊列,隊列中的任務(wù)都嚴(yán)格按照進入隊列的先后順序執(zhí)行。
在前一條任務(wù)執(zhí)行完畢后,立即執(zhí)行下一條任務(wù),直到任務(wù)隊列清空。
任務(wù)隊列的基本執(zhí)行流程如下:
- 給任務(wù)隊列添加任務(wù),并判斷執(zhí)行標(biāo)識;
- 如果執(zhí)行標(biāo)識為 false,則將任務(wù)從隊列中獨立出來;
- 開始執(zhí)行任務(wù),將執(zhí)行標(biāo)識置為 true;
- 執(zhí)行完畢后,判斷隊列是否為空,如果不為空,則繼續(xù)執(zhí)行下一條任務(wù);
- 直至任務(wù)隊列清空。
任務(wù)隊列一直在循環(huán)進行如上步驟。
任務(wù)隊列的 JS 實現(xiàn)
我們選擇使用數(shù)組來維護隊列的執(zhí)行順序,按照“先進先出“的原則,依次從數(shù)組的第一個元素開始往后執(zhí)行。
簡易代碼實現(xiàn)如下:
/** @format */
class TaskQueue {
constructor() {
this.queue = [];
this.isRunning = false;
}
/**
* @description 將任務(wù)添加至隊列
* @param {Promise} queueFunction
* @returns {undefined}
*/
addQueue(queueFunction) {
this.queue.push(queueFunction);
if (!this.isRunning) {
this.processQueue();
}
}
/**
* @description 如果隊列不為空,則開始處理隊列中的任務(wù),本次任務(wù)執(zhí)行完畢后,立刻開始下一條任務(wù)的執(zhí)行
* @param {}
*/
processQueue() {
if (this.queue.length > 0) {
this.isRunning = true;
const queueFunction = this.queue.shift();
queueFunction().finally(() => {
this.processQueue();
});
} else {
this.isRunning = false;
}
}
}測試
我們使用如下代碼來測試上述實現(xiàn):
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(" 任務(wù) 1");
};
let f2 = function (name) {
return new Promise((resolve) => {
setTimeout(() => {
console.log(`我是 f2`, name);
resolve();
}, 2000);
});
};
let f22 = async function () {
await f2(" 任務(wù) 2");
};
let f3 = function (name) {
return new Promise((resolve) => {
setTimeout(() => {
console.log(`我是 f3`, name);
resolve();
}, 1000);
});
};
let f33 = async function () {
await f3(" 任務(wù) 3");
};
taskQueue.addQueue(f11);
taskQueue.addQueue(f22);
taskQueue.addQueue(f33);
// 依次輸出:
// 我是 f1 任務(wù) 1
// 我是 f2 任務(wù) 2
// 我是 f3 任務(wù) 3如果不使用任務(wù)隊列,上面的測試應(yīng)該是按照 f1 -> f2 -> f3 的順序執(zhí)行,但是使用了任務(wù)隊列之后,f1 -> f2 -> f3 的順序執(zhí)行被改變了,這是因為任務(wù)隊列的執(zhí)行順序是按照添加的順序來的,而不是按照執(zhí)行順序來的。
總結(jié)
任務(wù)隊列的實現(xiàn)非常簡單,但是使用起來卻非常靈活,我們可以根據(jù)實際需求來決定任務(wù)隊列的執(zhí)行順序,也可以根據(jù)實際需求來決定任務(wù)隊列的執(zhí)行時機。
到此這篇關(guān)于基于JS實現(xiàn)任務(wù)隊列的示例代碼的文章就介紹到這了,更多相關(guān)JS任務(wù)隊列內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
兼容IE,firefox的獲取節(jié)點的文本值的javascript代碼
javascript獲取節(jié)點的文本值,已經(jīng)考慮了兼容性。大家可以放心使用。注意了這里的兼容沒有使用innerText,如果要使用兼容innerText,請參考腳本之家以前發(fā)布的文章。2009-12-12
JavaScript正則表達式替換字符串中圖片地址(img src)的方法
這篇文章主要介紹了JavaScript正則表達式替換字符串中圖片地址(img src)的方法,結(jié)合實例形式分析了JS正則替換的常用技巧與注意事項,需要的朋友可以參考下2017-01-01
前端JavaScript經(jīng)典之Promise詳解
Promise是為了解決回調(diào)地獄問題而誕生的,它提供了優(yōu)雅的異步回調(diào)解決方案,這篇文章主要介紹了前端JavaScript經(jīng)典之Promise的相關(guān)資料,需要的朋友可以參考下2024-09-09

