2024-07-03|閱讀時間 ‧ 約 26 分鐘

沒任務就停止,有任務就依序執行的小功能分享

使用場景

在網路速度有限的情況下,依序記錄不斷產生的資訊,能統計使用者在頁面上操作了哪些功能。

依序執行不斷產生的任務

依序執行不斷產生的任務


實現過程

打造一個類別(Executor),裡面有一個對外函式(recordData),會把使用者加入的任務不斷加入陣列內。這裡為了方便,讓使用者傳入字串,自動把字串變成過兩秒會印在console的任務函式。

class Executor {
constructor() {
this.pendingFunctionArray = [];
}

recordFunction = async (string) => {
await new Promise((resolve) => setTimeout(resolve, 2000));
console.log(`${string} finish`);
};

recordData = (string) => {
this.pendingFunctionArray.push(() => recordFunction(string));
}
}


加入一個函式,裡面有個回圈會依序執行任務。每次使用者呼叫recordData加入任務,就會呼叫這個函式,讓這個函式不斷執行,直到任務完成後停止。

class Executor {
constructor() {
this.pendingFunctionArray = [];
}

recordFunction = async (string) => {
await new Promise((resolve) => setTimeout(resolve, 2000));
console.log(`${string} finish`);
};

recordData = (string) => {
this.pendingFunctionArray.push(() => recordFunction(string));
this.scheduleTasks();
};

scheduleTasks = async () => {
while (true) {
if (this.pendingFunctionArray.length == 0) break;

const recordFunction = this.pendingFunctionArray.shift();
await recordFunction();
}
};
}


但這樣會產生多個scheduleTasks函式同時執行,可能產生預期外的結果。可以加入一個參數isExecuting來判斷,確保只有一個scheduleTasks函式在執行。

class Executor {
constructor() {
/**@type {Function[]} 待處理陣列 */
this.pendingFunctionArray = [];
/**是否正在排程執行任務 */
this.isExecuting = false;
}

recordFunction = async (string) => {
await new Promise((resolve) => setTimeout(resolve, 2000));
console.log(`${string} finish`);
};

recordData = (string) => {
this.pendingFunctionArray.push(() => recordFunction(string));
this.scheduleTasks();
};

scheduleTasks = async () => {
if (this.isExecuting) return;

this.isExecuting = true;
while (true) {
if (this.pendingFunctionArray.length == 0) {
this.isExecuting = false;
break;
}

const recordFunction = this.pendingFunctionArray.shift();
await recordFunction();
}
};
}


最後附上在線demo的鏈接:依序執行不斷產生的任務

分享至
成為作者繼續創作的動力吧!
© 2024 vocus All rights reserved.