嗨大家好,我是Eric,假設當我們有大量異步函數(api請求)要同時執行,我們不可能一次請求(網站可能會崩潰XD),所以我們可以限制一次請求的數量(比如10個),這樣可以有效提升 User 的用戶體驗,這就來談談實現這個需求的函數應用 - 併發任務。
簡單來說,併發就是同時執行多個任務。與串行(一個接一個地執行)相比,併發可以更高效。
我們通過一個例子來說明如何實現併發任務。
假設我們有一個任務列表,每個任務都是一個異步函數,我們想要同時執行其中的一部分。
mockTask 函數
首先,我們需要模擬一些異步任務。我們使用 mockTask 函數來生成這些任務。
function mockTask(count) {
const tasks = [];
for (let i = 0; i < count; i++) {
const asyncTask = async function() {
const startTime = Date.now();
console.log(`任務 ${i + 1}:任務開始...`);
// 模擬異步操作,比如等待1到5秒
const waitTime = Math.floor(Math.random() * 5000) + 1000;
await new Promise(resolve => setTimeout(resolve, waitTime));
const endTime = Date.now();
const elapsedTime = endTime - startTime;
console.log(`任務 ${i + 1}:完成,耗時 ${elapsedTime} ms`);
};
tasks.push(asyncTask);
}
return tasks;
}
接著,我們使用 paralleTask 函數來管理這些任務。
function paralleTask(tasks, parallelCount = 2) {
return new Promise((resolve, reject) => {
// 如果沒有任務,直接 resolve 任務完成
if(tasks.length === 0) {
resolve();
return;
}
let nextIndex = 0; // 記錄下一個任務的索引
let completedCount = 0; // 記錄已經完成的任務數量
// 輔助函數,用於執行任務
function _run() {
// 運行下一個任務
const task = tasks[nextIndex];
nextIndex++;
task().then(() => {
completedCount++;
if (nextIndex < tasks.length) {
// 如果還有任務,運行下一個
_run();
}else if(completedCount === tasks.length) {
// 完成的任務數量等於任務總數(完成所有任務),resolve
resolve();
}
})
}
// 依據併發數量,啟動任務
for (let i = 0; i < parallelCount && i < tasks.length ; i++) {
// 執行任務
_run();
}
});
}
組合使用
最後,我們可以這樣使用這兩個函數:
const task = mockTask(100);
paralleTask(task, 4).then(() => {
console.log('所有任務都已經完成');
});
透過使用 mockTask 和 paralleTask,我們可以方便地模擬和管理多個異步請求。這種併發模式不僅使我們能夠更高效,而且也提供了一種更加靈活的方式來執行任務。
這就是今天的全部內容,明天見~~