JavaScript 任务池
JavaScript 任務池
線程池
在多線程語言中,我們通常不會隨意的在需要啟動線程的時候去啟動 ,而是會選擇創(chuàng)建一個線程池。所謂線程池,本意其實就是(不止這些作用 ,其余作用可以自行查閱) :
- 節(jié)省操作系統(tǒng)資源
- 限制最大線程數(shù) 。
對于 JavaScript 來說,雖然不存在“啟動線程”這種問題,但我們還是可以通過類似的思想,來限制我們做異步操作的數(shù)量。
分析
首先我們需要一個數(shù)組 ,用它來存儲尚未執(zhí)行的任務,每個任務都是一個函數(shù) ,這個函數(shù)必須要返回一個 Promise。
type Task = () =>Promise;const tasks: Task[] = []; 其次我們需要一個方法來進行任務的添加。
function addTask(task: Task): void;最后我們需要一個函數(shù)來執(zhí)行我們所有的 task 。
而在這之前 ,我們還需要定義一個值 ,來定義同時執(zhí)行的異步任務的最大數(shù)量。
function execTasks(): void;實現(xiàn)
根據(jù)我們的分析 ,我們可以寫下基礎(chǔ)的代碼如下:
interface TaskPool { addTask(task: Task): void;}type Task = () =>Promise;function newTaskPool(max = 10): TaskPool { const tasks: Task[] = []; function addTask(task: Task): void { } function execTasks(): void { }} 新增任務非常簡單,我們寫出如下代碼填充 addTask 。
function addTask(task: Task): void { tasks.push(task);}接下來就是重頭戲。如何實現(xiàn) execTasks 方法來限制最大異步任務數(shù)量呢 ?
首先我們來明確一點 ,在下面這個場景中,如果 foo 函數(shù)是異步操作,那么是不會阻塞我們的代碼執(zhí)行的 。
console.log("Before");foo();console.log("After");那么我們可以這么操作 :
- 定義一個變量用來記錄當前的空閑任務數(shù)量;
- 執(zhí)行 execTasks 時 ,會選取當前任務數(shù)量和空閑任務數(shù)二者相比較小的一個;
- 根據(jù)該值進行循環(huán)