Сообщение от dc65k
|
const sendRequests = (requests, maxRequestsCount) => {
|
У такого подхода есть баг: если мы отправим 2 порции запросов, то они пойдут параллельно, т.е. будет в два раза больше запросов одновременно - у них ведь 2 независимые очереди.
Запилил исправленную версию, которая позволяет отправлять несколько порций. Причем, вторая порция может начать исполняться ещё до того, как завершится первая.
function createSendRequests(func, limit) {
let reqCount = 0;
const queue = [];
return function (requests) {
console.log('sendRequests for ', requests.join(','));
if (!requests || !requests.length) {
return Promise.resolve([]);
}
return new Promise((resolve) => {
const responses = Array.from({length: requests.length});
let curUrlInd = 0;
let requestDone = 0;
while (curUrlInd < requests.length && reqCount < limit) {
makeRequest(curUrlInd);
}
let inQueue = curUrlInd < requests.length;
if (inQueue) {
queue.push(nextRequest);
}
function nextRequest() {
makeRequest(curUrlInd);
if (inQueue && curUrlInd === requests.length) {
inQueue = false;
queue.shift();
}
}
function makeRequest(n) {
reqCount++;
curUrlInd++;
const req = requests[n];
console.log('request for ', req);
func(req).then(data => {
console.log('response for ', req);
responses[n] = {
data
};
}, (err) => {
responses[n] = {
error: err || 'error'
};
}).finally (() => {
reqCount--;
if (queue.length) {
queue[0]();
}
requestDone++;
if (requestDone === requests.length) {
resolve(responses);
}
});
}
});
};
}
// ----- использование -------------------------------------
function myFetch(req) {
return new Promise((res) => {
setTimeout(res, 1000, 'response for ' + req);
});
}
var sendRequests = createSendRequests(myFetch, 5);
sendRequests([
'reqA',
'reqB',
]).then((data) => {
console.log('responses 1', data);
});
sendRequests([
'req1',
'req2',
'req3',
'req4',
'req5',
'req6',
'req7',
]).then((data) => {
console.log('responses 2', data);
});
sendRequests([
'req8',
'req9',
'req10',
'req11',
'req12',
]).then((data) => {
console.log('responses 3', data);
});