每日一學~
前言
大家好,我是林三心,用最通俗易懂的話講最難的知識點是我的座右銘,基礎是進階的前提是我的初心。
背景
提起
控制並行
,大家應該不陌生,我們可以先來看看
多並行
,再去聊聊為什麽要去控制它
多並行
一般是指多個異步操作同時進行,而執行的環境中資源是有限的,短時間內過多的並行,會對所執行的環境造成很大的壓力,比如前端的瀏覽器,後端的伺服器,常見的多並行操作有:
前端的多個介面同時請求
前端多條數據異步處理
Nodejs的多個數據操作同時進行
Nodejs對多個檔同時進行修改
正是因為
多並行
會造成壓力,所以我們才需要去控制他,降低這個壓力~,比如我可以控制最大並行數是 3,這樣的話即使有100個並行,我也能保證最多同時並行的最大數量是 3
程式碼實作
實作思路
大致思路就是,假設現在有 9 個並行,我設定最大並行為 3,那麽我將會走下面這些步驟:
1、先定好三個坑位
2、讓前三個並行進去坑位執行
3、看哪個坑位並行先執行完,就從剩余的並行中拿一個進去補坑
4、一直重復第 3 步,一直到所有並行執行完
Promise.all
在進行多並行的時候,我們通常會使用
Promise.all
,但是
Promise.all
並不能控制並行,或者說它本來就沒這個能力,我們可以看下面的例子
最後是同時輸出,這說明這幾個並行是同時發生的
所以我們需要做一些改造,讓
Promise.all
執行 promises 時支持控制並行,但是我們改造的不應該是
Promise.all
,而是這一個個的
fetchFn
期望效果
實作 limitFn
我們需要在函式內部維護兩個變量:
queue:佇列,用來存每一個改造過的並行
activeCount:用來記錄正在執行的並行數
並聲明函式 generator ,這個函式返回一個 Promise,因為 Promise.all 最好是接收一個 Promise 陣列
接下來我們來實作
enqueue
這個函式做兩件事:
將每一個 fetchFn 放進佇列裏
將坑位裏的 fetchFn 先執行
假如我設定最大並行數為 2,那麽這一段程式碼在一開始的時候只會執行 2 次,因為一開始只會有 2 次符合 if 判斷,大家可以思考一下為什麽~
一開始執行 2 次,說明這時候兩個坑位已經各自有一個 fetchFn 在執行了
接下來我們實作
run
函式,這個函式是用來包裝 fetch 的,他完成幾件事情:
1、將 activeCount++ ,這時候執行中的並行數 +1
2、將 fetchFn 執行,並把結果 resolve 出去,說明這個並行執行完了
3、將 activeCount--,這時候執行中的並行數 -1
4、從 queue 中取一個並行,拿來補坑執行
其實第 3、4 步,是在 next 函式裏面執行的
完整程式碼
const limitFn = (limit) => {
const queue = [];
let activeCount = 0;
const next = () => {
activeCount--;
if (queue.length > 0) {
queue.shift()();
}
};
const run = async (fn, resolve, ...args) => {
activeCount++;
const result = (async () => fn(...args))();
try {
const res = await result;
resolve(res);
} catch { }
next();
};
const enqueue = (fn, resolve, ...args) => {
queue.push(run.bind(null, fn, resolve, ...args));
if (activeCount < limit && queue.length > 0) {
queue.shift()();
}
};
const generator = (fn, ...args) =>
newPromise((resolve) => {
enqueue(fn, resolve, ...args);
});
return generator;
};
這不是我寫的
其實這是一個很出名的庫的源碼,就是
p-limit
,哈哈,但是重要嗎?知識嘛,讀懂了,它就是你的,到時跟面試官嘮嗑的時候,他哪知道是不是真的是你寫的~
結語
我是林三心
一個待過 小型toG型外包公司、大型外包公司、小公司、潛力型創業公司、大公司 的作死型前端選手;
一個偏前端的全幹工程師;
一個不正經的金塊作者;
逗比的B站up主;
不帥的小紅書博主;
喜歡打鐵的籃球菜鳥;
喜歡歷史的乏味少年;
喜歡rap的五音不全弱雞
如果你想一起學習前端,一起摸魚,一起研究簡歷最佳化,一起研究面試進步,一起交流歷史音樂籃球rap,可以來俺的摸魚學習群哈哈,點這個,有7000多名前端小夥伴在等著一起學習哦 -->
廣州的兄弟可以約飯哦,或者約球~我負責打鐵,你負責進球,謝謝~