最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript?Promise多并發(fā)問題的解決方法詳解

 更新時間:2023年09月19日 11:25:07   作者:喆星高照  
提起控制并發(fā),大家應該不陌生,這篇文章主要來和大家介紹一下JavaScript如何解決Promise多并發(fā)問題,感興趣的小伙伴可以跟隨小編一起學習一下

提起控制并發(fā),大家應該不陌生,我們可以先來看看多并發(fā),再去聊聊為什么要去控制它

多并發(fā)一般是指多個異步操作同時進行,而運行的環(huán)境中資源是有限的,短時間內(nèi)過多的并發(fā),會對所運行的環(huán)境造成很大的壓力,比如前端的瀏覽器,后端的服務器,常見的多并發(fā)操作有:

  • 前端的多個接口同時請求
  • 前端多條數(shù)據(jù)異步處理
  • Nodejs的多個數(shù)據(jù)操作同時進行
  • Nodejs對多個文件同時進行修改

正是因為多并發(fā)會造成壓力,所以我們才需要去控制他,降低這個壓力~,比如我可以控制最大并發(fā)數(shù)是 3,這樣的話即使有100個并發(fā),我也能保證最多同時并發(fā)的最大數(shù)量是 3

代碼實現(xiàn)

實現(xiàn)思路

大致思路就是,假設(shè)現(xiàn)在有 9 個并發(fā),我設(shè)置最大并發(fā)為 3,那么我將會走下面這些步驟:

  • 1、先定好三個坑位
  • 2、讓前三個并發(fā)進去坑位執(zhí)行
  • 3、看哪個坑位并發(fā)先執(zhí)行完,就從剩余的并發(fā)中拿一個進去補坑
  • 4、一直重復第 3 步,一直到所有并發(fā)執(zhí)行完

Promise.all

在進行多并發(fā)的時候,我們通常會使用Promise.all,但是Promise.all并不能控制并發(fā),或者說它本來就沒這個能力,我們可以看下面的例子

const fetchFn = (delay, index) => {
  return new Promise(resolve => {
    console.log(index)
    setTimeout(() => {
      resolve(index)
    }, delay);
  })
}
const promises = [
  fetchFn(1000, 1),
  fetchFn(1000, 2),
  fetchFn(1000, 3),
  fetchFn(1000, 4),
  fetchFn(1000, 5),
  fetchFn(1000, 6)
]
Promise.all(promises)

最后是同時輸出,這說明這幾個并發(fā)是同時發(fā)生的

所以我們需要做一些改造,讓Promise.all執(zhí)行 promises 時支持控制并發(fā),但是我們改造的不應該是Promise.all,而是這一個個的fetchFn

期望效果

const limitFn = (limit) => {
  // ...coding
}
// 最大并發(fā)數(shù) 2
const generator = limitFn(2)
const promises = [
  generator(() => fetchFn(1000, 1)),
  generator(() => fetchFn(1000, 2)),
  generator(() => fetchFn(1000, 3)),
  generator(() => fetchFn(1000, 4)),
  generator(() => fetchFn(1000, 5)),
  generator(() => fetchFn(1000, 6))
]
Promise.all(promises)

實現(xiàn) limitFn

我們需要在函數(shù)內(nèi)部維護兩個變量:

  • queue:隊列,用來存每一個改造過的并發(fā)
  • activeCount:用來記錄正在執(zhí)行的并發(fā)數(shù)

并聲明函數(shù) generator ,這個函數(shù)返回一個 Promise,因為 Promise.all 最好是接收一個 Promise 數(shù)組

const limitFn = (concurrency) => {
  const queue = [];
  let activeCount = 0;
  const generator = (fn, ...args) =>
    new Promise((resolve) => {
      enqueue(fn, resolve, ...args);
    });
  return generator;
};

接下來我們來實現(xiàn) enqueue 這個函數(shù)做兩件事:

  • 將每一個 fetchFn 放進隊列里
  • 將坑位里的 fetchFn 先執(zhí)行
const enqueue = (fn, resolve, ...args) => {
  queue.push(run.bind(null, fn, resolve, ...args));
  if (activeCount < limit && queue.length > 0) {
    queue.shift()();
  }
};

假如我設(shè)置最大并發(fā)數(shù)為 2,那么這一段代碼在一開始的時候只會執(zhí)行 2 次,因為一開始只會有 2 次符合 if 判斷,大家可以思考一下為什么~

if (activeCount < limit && queue.length > 0) {
    queue.shift()(); // 這段代碼
  }

一開始執(zhí)行 2 次,說明這時候兩個坑位已經(jīng)各自有一個 fetchFn 在執(zhí)行了

接下來我們實現(xiàn) run 函數(shù),這個函數(shù)是用來包裝 fetch 的,他完成幾件事情:

  • 1、將 activeCount++ ,這時候執(zhí)行中的并發(fā)數(shù) +1
  • 2、將 fetchFn 執(zhí)行,并把結(jié)果 resolve 出去,說明這個并發(fā)執(zhí)行完了
  • 3、將 activeCount--,這時候執(zhí)行中的并發(fā)數(shù) -1
  • 4、從 queue 中取一個并發(fā),拿來補坑執(zhí)行
const run = async (fn, resolve, ...args) => {
  activeCount++;
  const result = (async () => fn(...args))();
  try {
    const res = await result;
    resolve(res);
  } catch { }
  next();
};

其實第 3、4 步,是在 next 函數(shù)里面執(zhí)行的

const next = () => {
  activeCount--;
  if (queue.length > 0) {
    queue.shift()();
  }
};

完整代碼

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) =>
    new Promise((resolve) => {
      enqueue(fn, resolve, ...args);
    });
  return generator;
};

這不是我寫的

其實這是一個很出名的庫的源碼,就是p-limit,哈哈,但是重要嗎?知識嘛,讀懂了,它就是你的,到時跟面試官嘮嗑的時候,他哪知道是不是真的是你寫的~

到此這篇關(guān)于JavaScript Promise多并發(fā)問題的解決方法詳解的文章就介紹到這了,更多相關(guān)JavaScript Promise內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 基于JS實現(xiàn)類似支付寶支付密碼輸入框

    基于JS實現(xiàn)類似支付寶支付密碼輸入框

    這篇文章主要介紹了基于JS實現(xiàn)類似支付寶支付密碼輸入框功能,密碼框只準輸入數(shù)字且只可以輸入6位數(shù)字,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-09-09
  • 前端JavaScript實現(xiàn)本地模糊搜索功能的方法實例

    前端JavaScript實現(xiàn)本地模糊搜索功能的方法實例

    對于模糊查詢,一般都是傳關(guān)鍵字給后端,由后端來做。但是有時候一些輕量級的列表前端來做可以減少ajax請求,在一定程度上提高用戶體驗,這篇文章主要給大家介紹了關(guān)于前端JavaScript如何實現(xiàn)本地模糊搜索功能的相關(guān)資料,需要的朋友可以參考下
    2021-07-07
  • javascript中定義私有方法說明(private method)

    javascript中定義私有方法說明(private method)

    本篇文章主要是對javascript中定義私有方法(private method)進行了介紹,需要的朋友可以過來參考下,希望對大家有所幫助
    2014-01-01
  • 詳解JavaScript跨域總結(jié)與解決辦法

    詳解JavaScript跨域總結(jié)與解決辦法

    本篇文章主要介紹了JavaScript跨域,詳細的總結(jié)了什么是跨域,并介紹了幾種解決辦法,感興趣的小伙伴們可以參考一下。
    2016-10-10
  • javascript的console.log()用法小結(jié)

    javascript的console.log()用法小結(jié)

    console.log 原先是 Firefox 的 專利 ,嚴格說是安裝了 Firebugs 之后的 Firefox 所獨有的調(diào)試 絕招
    2012-05-05
  • JavaScript必知必會(六) delete in instanceof

    JavaScript必知必會(六) delete in instanceof

    這篇文章主要介紹了JavaScript必知必會(六) delete in instanceof的相關(guān)資料,非常不錯具有參考借鑒價值,需要的朋友可以參考下
    2016-06-06
  • js 事件截取enter按鍵頁面提交事件示例代碼

    js 事件截取enter按鍵頁面提交事件示例代碼

    本篇文章主要是對js 事件截取enter按鍵頁面提交事件示例代碼進行了介紹,需要的朋友可以過來參考下,希望對大家有所幫助
    2014-03-03
  • Javascript改變CSS樣式(局部和全局)

    Javascript改變CSS樣式(局部和全局)

    改變CSS樣式分為局部和全局,下面為大家介紹下使用Javascript具體的實現(xiàn),感興趣的朋友可以參考下
    2013-12-12
  • 使用canvas進行圖像編輯的實例

    使用canvas進行圖像編輯的實例

    下面小編就為大家?guī)硪黄褂胏anvas進行圖像編輯的實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-08-08
  • JavaScript中click事件默認等待300ms延遲問題詳解

    JavaScript中click事件默認等待300ms延遲問題詳解

    這篇文章主要介紹了JavaScript中click事件默認等待300ms延遲問題,當用戶單擊頁面元素時,瀏覽器無法立刻判斷用戶的操作是單次點擊還是雙擊,因此瀏覽器會在首次點擊后默認等待300ms左右,下面來深入介紹一下,需要的朋友可以參考下
    2026-01-01

最新評論

诏安县| 太仓市| 天长市| 莎车县| 霍城县| 拉萨市| 延长县| 文山县| 高陵县| 陇川县| 华容县| 林口县| 澜沧| 武川县| 新平| 揭东县| 建湖县| 塔城市| 滕州市| 武邑县| 玛曲县| 惠来县| 科尔| 丹江口市| 全南县| 唐山市| 竹溪县| 科技| 昌邑市| 涿州市| 蕲春县| 明星| 胶南市| 石河子市| 淮北市| 策勒县| 泰宁县| 华阴市| 乌拉特中旗| 全州县| 长顺县|