天天看點

在 JavaScript 中如何使用Promise控制100個請求并發?

作者:猿習社
“面試時,面試官詢問如何通過Promise控制100個請求并發” 該如何回答呢?
在 JavaScript 中如何使用Promise控制100個請求并發?

衆所周知,在現代Web開發中,異步已經成為不可或缺的一部分;

當處理大量請求時,如何保持并發是一個非常關鍵的步驟,Promise異步可以避免代碼阻塞一種非常有效的解決方案;

在 JavaScript 中如何使用Promise控制100個請求并發?

今天我們來讨論一下如何使用Promise控制100個請求的并發操作;

在開始之前,我們簡單回顧一下Promise的幾個關鍵的基礎知識;

Promise 三種狀态:

在 JavaScript 中如何使用Promise控制100個請求并發?
  • pending (等待狀态)
  • fulfilled (已完成)
  • rejected (已拒絕)

Promise 的幾個常用方法:

then

該方法用于指定Promise對象狀态變為fulfilled時的回調函數onFulfilled,以及狀态變為rejected時的回調函數onRejected。

當Promise對象處于fulfilled狀态時,将調用onFulfilled函數,并将Promise的結果值作為參數傳遞給它。

當Promise對象處于rejected狀态時,将調用onRejected函數,并将Promise的拒因(錯誤資訊)作為參數傳遞給它。

該方法傳回一個新的Promise對象,可以通過鍊式調用then()來進行多個操作。

catch

該方法用于指定Promise對象狀态變為rejected時的回調函數onRejected。

它相當于調用then(null, onRejected),用于捕獲Promise鍊中任何一個Promise的拒因。

如果Promise鍊中任意一個Promise被拒絕,且沒有提供對應的錯誤處理回調函數,則會将錯誤傳遞給最近的catch()方法來處理。

finally

該方法用于指定Promise對象狀态變為fulfilled或rejected時的回調函數onFinally,無論Promise的狀态如何,都會執行該回調函數。

在finally()回調函數中,可以執行一些無論Promise成功還是失敗都需要進行的清理操作,比如關閉檔案、釋放資源等。

finally()回調函數不會修改Promise的狀态或結果,它隻是在Promise鍊中傳遞原始的成功或拒絕值。

race

Promise.race()方法接收一個可疊代對象作為參數,并傳回一個新的Promise對象。

當傳入的可疊代對象中的任意一個Promise對象狀态發生變化,新的Promise對象将立即采用該Promise對象的狀态和結果。傳回的Promise對象将具有與第一個解決的Promise對象相同的狀态和結果。

all

Promise.all()方法接收一個可疊代對象作為參數,并傳回一個新的Promise對象。

當傳入的可疊代對象中的所有Promise對象都變為fulfilled狀态時,新的Promise對象将變為fulfilled狀态。

如果傳入的可疊代對象中的任意一個Promise對象變為rejected狀态,則新的Promise對象将立即變為rejected狀态,且其拒因為第一個被拒絕的Promise的拒因。

傳回的Promise對象将包含一個數組,數組的順序與傳入的可疊代對象中的Promise對象順序一緻,每個元素是對應Promise對象的結果值。

實作思路

1、将100個請求轉換成一個請求數組,每個請求都傳回一個promise對象;

2、在每個請求中使用 await 來等待請求結果;

3、控制并發請求數量,用一個計數器來跟蹤正在進行請求的數量,在每次發起新的請求之前檢查計數器是否已經達到最大并發數;如果沒有達到最大并發數,增加計數器,bing發起新請求,否則等待之前的請求完成再發起新請求。

實作步驟:

完整代碼如下:

// 并發請求數量
const concurrency = 10;

// 請求函數示例
function fetchData(url) {
  return new Promise((resolve, reject) => {
    fetch(url)
      .then(data => resolve(data))
      .catch(error => reject(error));
  });
}

// 并發控制函數
async function requests(urls) {
  const results = [];
  let count = 0;

  // 定義異步處理函數
  async function handleRequest(url) {
    try {
      const result = await fetchData(url);
      return result;
    } catch (error) {
      throw new Error(`Error fetching ${url}: ${error}`);
    }
  }

  // 循環發起請求
  while (urls.length) {
    // 控制并發請求數量
    if (count < concurrency) {
      const url = urls.shift();
      count++;
      results.push(handleRequest(url).finally(() => {
        count--;
      }));
    } else {
      await Promise.race(results);
    }
  }

  // 等待所有請求完成
  await Promise.all(results);

  return results;
}

// 100個請求的URL數組示例,可以根據實際需求修改
const urls = [
  'https://example.com/api/1',
  'https://example.com/api/2',
  'https://example.com/api/4',
  'https://example.com/api/5',
  'https://example.com/api/6',
  // ... 
  'https://example.com/api/100'
];

// 調用并發控制函數
requests(urls)
  .then(results => {
    console.log('所有請求完成', results);
  })
  .catch(error => {
    console.error('請求出錯', error);
  });
           

控制100個請求的并發是一個挑戰,但借助Promise的特性,我們可以輕松地管理并發性,并擷取每個請求的結果。

通過将請求分成小組,并使用Promise.all()進行并發處理,我們可以更高效地處理大量請求。

說明:本文首發頭條,歡迎轉載!轉載請标注來源即可,無需授權!創作不易,喜歡我的文章,記得添加【關注】哦!再次感謝你的支援!

❀ 長按【點贊】會有驚喜哦!❀

~End~

繼續閱讀