[英]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);
}
上面的示例是我的代碼的標准版本 - 我也嘗試了兩種不同的方法:
兩種方法都有效 - 但它們似乎都沒有加速任何東西......?? 我有一個想法是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.