[英]API can't handle my request because of template literals to make the API dynamic
[英]Make several requests to an API that can only handle 20 request a minute
我有一個返回promise的方法,並且在內部該方法調用一個API,該API每分鍾只能有20個請求。 問題是我有很多對象(大約300個),並且我想為每個對象調用API。
目前,我有以下代碼:
const bigArray = [.....];
Promise.all(bigArray.map(apiFetch)).then((data) => {
...
});
但是它不處理時序約束。 我希望我可以使用來自lodash
_.chunk和_.debounce之類的東西,但是我lodash
這個問題。 有人可以幫我嗎?
如果可以使用Bluebird Promise庫,則它具有內置的並發功能,可讓您管理一組異步操作,一次最多可處理N個。
var Promise = require('bluebird');
const bigArray = [....];
Promise.map(bigArray, apiFetch, {concurrency: 20}).then(function(data) {
// all done here
});
關於這個接口的好處是它將保持20個請求運行。 它將啟動20,然后每次完成一次,它將啟動另一個。 因此,這可能比發送20個,等待所有人完成,再發送20個等等的效率更高。
這也以與bigArray
完全相同的順序提供結果,因此您可以確定哪個結果與哪個請求一起進行。
當然,您可以使用計數器使用通用的Promise自己編寫代碼,但是由於它已經在Bluebird庫中構建,我想我建議這樣做。
異步庫也有類似的並發控制,盡管它顯然不是基於promise的。
這是一個僅使用ES6 Promise的手動編碼版本,可保證結果順序並始終保持20個請求在飛行中(直到剩下20個請求為止),以實現最大吞吐量:
function pMap(array, fn, limit) {
return new Promise(function(resolve, reject) {
var index = 0, cnt = 0, stop = false, results = new Array(array.length);
function run() {
while (!stop && index < array.length && cnt < limit) {
(function(i) {
++cnt;
++index;
fn(array[i]).then(function(data) {
results[i] = data;
--cnt;
// see if we are done or should run more requests
if (cnt === 0 && index === array.length) {
resolve(results);
} else {
run();
}
}, function(err) {
// set stop flag so no more requests will be sent
stop = true;
--cnt;
reject(err);
});
})(index);
}
}
run();
});
}
pMap(bigArray, apiFetch, 20).then(function(data) {
// all done here
}, function(err) {
// error here
});
在這里工作的演示: http : //jsfiddle.net/jfriend00/v98735uu/
您可以每分鍾發送1個包含20個請求的塊,或者每3秒將其間隔1個請求(這可能是API所有者更喜歡的)。
function rateLimitedRequests(array, chunkSize) {
var delay = 3000 * chunkSize;
var remaining = array.length;
var promises = [];
var addPromises = function(newPromises) {
Array.prototype.push.apply(promises, newPromises);
if (remaining -= newPromises.length == 0) {
Promise.all(promises).then((data) => {
... // do your thing
});
}
};
(function request() {
addPromises(array.splice(0, chunkSize).map(apiFetch));
if (array.length) {
setTimeout(request, delay);
}
})();
}
要每3秒撥打1個電話:
rateLimitedRequests(bigArray, 1);
或每分鍾20個:
rateLimitedRequests(bigArray, 20);
如果您更喜歡使用_.chunk
和 1 _.debounce
_.throttle
:
function rateLimitedRequests(array, chunkSize) {
var delay = 3000 * chunkSize;
var remaining = array.length;
var promises = [];
var addPromises = function(newPromises) {
Array.prototype.push.apply(promises, newPromises);
if (remaining -= newPromises.length == 0) {
Promise.all(promises).then((data) => {
... // do your thing
});
}
};
var chunks = _.chunk(array, chunkSize);
var throttledFn = _.throttle(function() {
addPromises(chunks.pop().map(apiFetch));
}, delay, {leading: true});
for (var i = 0; i < chunks.length; i++) {
throttledFn();
}
}
1您可能需要_.throttle
因為它在延遲后執行每個函數調用,而_.debounce
將多個調用分組為一個調用。 看到這個文章從鏈接的文檔
防抖動 :可以將其視為“將多個事件組合在一起”。 想象您回家,進入電梯,門正在關閉……突然間,您的鄰居出現在大廳里,試圖跳上電梯。 要有禮貌! 並為他打開門:您正在取消電梯的離開。 考慮到第三人可能再次發生相同的情況,依此類推……可能會將出發時間延遲了幾分鍾。
油門 :將其視為閥門,它調節執行流程。 我們可以確定某個函數在特定時間內可以被調用的最大次數。 因此,在電梯類比中,您很有禮貌地允許人們進入10秒鍾,但是一旦延遲過去,您就必須走!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.