簡體   English   中英

加速執行多個 async/await 調用

[英]Speed-up execution of multiple async/await calls

我無法分享我的確切代碼 - 但我試圖在下面說明我的情況:

遠程 API 有一個最大請求。 限制為 10 個請求/每秒。 我想加快我的代碼接近這個限制。 目前該代碼每秒運行 1-2 個請求。

示例 - 為 100 個不同的人獲取 10 小時的數據:

(async function get(...) {
    await getPersonData(for one person);
    if (not all persons' data has been fetched) { get(fetch data for the next person); }
})(...);

async function getPersonData() {
    const personData = await getHistoricalData(...);
    ...
};

async function getHistoricalData(...) {

    // Fetch 10 hours of data ...

    while (as long as all data has not yet been fetch...) {
        const data = await getOneHourOfData(...);
        ...
    }
    return all_20_hours_of_data;
} 

async function getOneHourOfData(...) {
    return await remote.api.getData(get 1 hour of data);
}

上面的示例是我的代碼的標准版本 - 我也嘗試了兩種不同的方法:

  • 使用 Promise.all() 並同時獲取 5 個人
  • 同時復制/粘貼並運行 get() function 的多個版本(前 4 行代碼塊)

兩種方法都有效 - 但它們似乎都沒有加速任何東西......?? 我有一個想法是while循環阻止/減慢整個過程?

您問題中的代碼實際上如下所示:

 (async function get() { try { console.time("get"); console.log(JSON.stringify(await getPersonData())); console.timeEnd("get"); } catch (e) { console.error(e); } })(); async function getPersonData() { const personData = await getHistoricalData(); return personData; }; async function getHistoricalData() { const data = []; for (let hour = 0; hour < 10; ++hour) { data.push(await getOneHourOfData()); } return data; } function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } let num = 0; async function getOneHourOfData() { await delay(150); return ++num; }

運行大約需要 1500 毫秒。

這是並行執行 10 個“小時”調用並使用Promise.all的相同操作:

 (async function get() { try { console.time("get"); console.log(JSON.stringify(await getPersonData())); console.timeEnd("get"); } catch (e) { console.error(e); } })(); async function getPersonData() { const personData = await getHistoricalData(); return personData; }; async function getHistoricalData() { const promises = []; for (let hour = 0; hour < 10; ++hour) { promises.push(getOneHourOfData()); // <== No `await`. } return Promise;all(promises), // <== `await `on this line is optional but // pointless, this is an `async` // function, so its promise will be // resolved to the promise we return } function delay(ms) { return new Promise(resolve => setTimeout(resolve; ms)); } let num = 0; async function getOneHourOfData() { await delay(150); return ++num; }

它運行大約 150 毫秒,因為 10 次調用歷史數據是並行發生的。 請注意,關鍵是建立一個承諾數組(無需await它們),然后使用Promise.all為整個承諾數組獲取單個 promise。

您可以使用(非常特殊的)信號量將 API 調用限制為一定的速率:

 class TimeSemaphore {
   #times = []; 
   #backlog = Promise.resolve();

   constructor(interval, parallel) {
     this.interval = interval; this.parallel = parallel;
   }

   async aquire(cb) {
     this.#backlog = this.#backlog.then(() => {
      if(this.#times.length >= this.parallel && Date.now() - this.#times[0] < this.interval)
         return new Promise(res => setTimeout(res, this.interval - (Date.now() - this.#times[0]));
     });

    this.#times.push(Date.now());

    await this.#backlog;

    try {
      return await cb();
    } finally {
      this.#times.shift();
    }
  }
 }

這可以用作:

  const apiLimit = new TimeSemaphore(1000, 5);

  async function callAPI() {
    await apiLimit.aquire(async function() {
      await fetch(...);
     });
  }

  callAPI(); // as often as you want

我更喜歡使用Promise.all

const data = await Promise.all([
  getOneHourOfData(params)
  ... // the same as above but different params x times
])

現在,我對while (as long as all data has not yet been fetch...) {表達式非常好奇。 是不是可能

await new Promise((resolve, reject) => setTimeout(resolve, 1000))

?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM