![Старый](/forum/images/ca_serenity/statusicon/post_old.gif)
31.08.2021, 13:25
|
Аспирант
|
|
Регистрация: 19.05.2020
Сообщений: 46
|
|
Как реализовать задачу с одновременными запросами на сервер?
Всем привет. Есть функция, она принимает на вход массив адресов на которые будет происходить запрос и количество максимальных запросов (количество максимальных запросов в очереди). Если количество запросов больше чем второй параметр (очередь заполнена), то мы должны дождаться когда можно будет уменьшить очередь и продолжить делать следующие запросы по описанному принципу заполнения очереди.
Ниже я написал начало решения, вопрос именно в том как в коде написать очистку очереди и продолжение выполнение запросов?
const sendRequests = (requests, maxRequestsCount) => {
return new Promise(resolve => {
const responses = [];
let requestsCount = 0;
for (let i = 0; i < requests.length; i++) {
const request = requests[i];
requestsCount += 1;
if (requestsCount !== maxRequestsCount) {
makeRequest(request);
}
}
function makeRequest(url) {
return fetch(url)
.then(result => result.json())
.catch(error => error)
.then(result => {
responses.push(result);
resolve(responses);
});
}
});
}
console.log(
sendRequests([
'https://jsonplaceholder.typicode.com/todos/2',
'https://jsonplaceholder.typicode.com/todos/4',
'https://jsonplaceholder.typicode.com/todos/10',
'https://jsonplaceholder.typicode.com/todos/18'
], 3).then(response => {
console.log(response);
})
);
|
|
![Старый](/forum/images/ca_serenity/statusicon/post_old.gif)
31.08.2021, 15:37
|
![Аватар для ksa](https://javascript.ru/forum/image.php?u=8616&dateline=1282216923) |
CacheVar
|
|
Регистрация: 19.08.2010
Сообщений: 14,235
|
|
Сообщение от dc65k
|
то мы должны дождаться когда можно будет уменьшить очередь
|
И когда это наступает?
|
|
![Старый](/forum/images/ca_serenity/statusicon/post_old.gif)
31.08.2021, 15:47
|
Аспирант
|
|
Регистрация: 19.05.2020
Сообщений: 46
|
|
Очередь считается заполненной, когда ушло максимальное количество запросов (второй параметр). Очистить очередь на один запрос можно тогда, когда этот запрос выполнился.
Последний раз редактировалось dc65k, 31.08.2021 в 16:12.
|
|
![Старый](/forum/images/ca_serenity/statusicon/post_old.gif)
31.08.2021, 18:24
|
![Аватар для voraa](https://javascript.ru/forum/image.php?u=69123&dateline=1640150450) |
Профессор
|
|
Регистрация: 03.02.2020
Сообщений: 2,754
|
|
Может такой вариант
const sendRequests = (requests, maxRequestsCount) => {
return new Promise(resolve => {
const responses = Array.from({length: requests.length}, _ => null);
let curUrlInd = 0;
let requestDone = 0;
for (let i = 0; i < maxRequestsCount; i++) {
makeRequest(requests[i], i);
}
curUrlInd = maxRequestsCount;
function makeRequest(url, n) {
return fetch(url)
.then(result => result.json())
.catch(error => error)
.then(result => {
responses[n] = result;
})
.finally (() => {
if (curUrlInd < requests.length) {
makeRequest(requests[curUrlInd], curUrlInd);
curUrlInd++;
}
requestDone ++;
if (requestDone === requests.length) {
resolve(responses);
}
});
}
});
}
console.log(
sendRequests([
'https://jsonplaceholder.typicode.com/todos/2',
'https://jsonplaceholder.typicode.com/todos/4',
'https://jsonplaceholder.typicode.com/todos/10',
'https://jsonplaceholder.typicode.com/todos/18'
], 3).then(response => {
console.log(response);
})
);
Последний раз редактировалось voraa, 31.08.2021 в 19:18.
|
|
![Старый](/forum/images/ca_serenity/statusicon/post_old.gif)
31.08.2021, 19:10
|
![Аватар для ksa](https://javascript.ru/forum/image.php?u=8616&dateline=1282216923) |
CacheVar
|
|
Регистрация: 19.08.2010
Сообщений: 14,235
|
|
Сообщение от dc65k
|
Очистить очередь на один запрос можно тогда, когда этот запрос выполнился.
|
Тогда и запускай следующий УРЛ... И так пока они не кончатся.
|
|
![Старый](/forum/images/ca_serenity/statusicon/post_old.gif)
31.08.2021, 20:20
|
![Аватар для Aetae](https://javascript.ru/forum/image.php?u=4993&dateline=1299014303) |
Тлен
|
|
Регистрация: 02.01.2010
Сообщений: 6,590
|
|
Сообщение от voraa
|
Может такой вариант
const responses = Array.from({length: requests.length}, _ => null);
|
Зачема так усложнять? Есть же классика:
const responses = new Array(requests.length);
P.S. И да, работать как требует dc65k оно не будет: осле первых трёх количество запросов будет нарастать без контроля, а должно быть всегда три.)
__________________
29375, 35
Последний раз редактировалось Aetae, 31.08.2021 в 20:23.
|
|
![Старый](/forum/images/ca_serenity/statusicon/post_old.gif)
31.08.2021, 20:36
|
![Аватар для voraa](https://javascript.ru/forum/image.php?u=69123&dateline=1640150450) |
Профессор
|
|
Регистрация: 03.02.2020
Сообщений: 2,754
|
|
Сообщение от Aetae
|
Зачема так усложнять? Есть же классика:
const responses = new Array(requests.length);
|
Классика - не значит хорошо.
В данном случае, конечно без разницы, но я так не делаю
new Array(n) создает "дырявый" массив, который очень неэффективен при всяких оптимизациях.
|
|
![Старый](/forum/images/ca_serenity/statusicon/post_old.gif)
31.08.2021, 20:41
|
![Аватар для voraa](https://javascript.ru/forum/image.php?u=69123&dateline=1640150450) |
Профессор
|
|
Регистрация: 03.02.2020
Сообщений: 2,754
|
|
Сообщение от Aetae
|
P.S. И да, работать как требует dc65k оно не будет: осле первых трёх количество запросов будет нарастать без контроля, а должно быть всегда три.)
|
Заменим fetch на другую функцию и проверим
<html>
<script>
const fakefetch = (url) =>{
return new Promise (res => {
dt = (Math.random()*2+1)*1000 | 0
setTimeout(() => res({url:url, dt: dt}), dt)
})
}
const sendRequests = (requests, maxRequestsCount) => {
return new Promise(resolve => {
const responses = Array.from({length: requests.length}, _ => null);
let curUrlInd = 0;
let requestDone = 0;
for (let i = 0; i < maxRequestsCount; i++) {
const request = requests[i];
makeRequest(requests[i], i);
}
curUrlInd = maxRequestsCount
async function makeRequest(url, n) {
console.log('Request', n)
return fakefetch(url)
// .then(result => result.json())
// .catch(error => error)
.then(result => {
responses[n] = result;
})
.finally (() => {
requestDone ++;
console.log('Done', n, requestDone)
if (curUrlInd < requests.length) {
makeRequest(requests[curUrlInd], curUrlInd);
curUrlInd++;
}
if (requestDone === requests.length) {
console.log ('Done All')
resolve(responses);
}
});
}
});
}
sendRequests([
'https://jsonplaceholder.typicode.com/todos/2',
'https://jsonplaceholder.typicode.com/todos/4',
'https://jsonplaceholder.typicode.com/todos/10',
'https://jsonplaceholder.typicode.com/todos/18',
'https://jsonplaceholder.typicode.com/todos/20',
'https://jsonplaceholder.typicode.com/todos/40',
'https://jsonplaceholder.typicode.com/todos/100',
'https://jsonplaceholder.typicode.com/todos/180'
], 3).then(response => {
console.log(response);
})
</script>
</html>
Нарастать не будет - новый запрос посылается, когда какой то из ранее посланных закончится.
Последний раз редактировалось voraa, 31.08.2021 в 20:47.
|
|
![Старый](/forum/images/ca_serenity/statusicon/post_old.gif)
31.08.2021, 20:55
|
![Аватар для Aetae](https://javascript.ru/forum/image.php?u=4993&dateline=1299014303) |
Тлен
|
|
Регистрация: 02.01.2010
Сообщений: 6,590
|
|
voraa, да согласен, тупанул.)
По поводу new Array - я его использую только именно в таком случае и ни в каком ином. Считаю что использовать подходящие инструменты в подходящих местах - стоит, а откидывать те или иные вещи скопом только потому, что в некоторых ситуациях(прекрасно известных) они могут привести к неприятным последствиями, ограничивая себя узкими рамками "безопасного" кода - не стоит.)
Обычно всё это сводится к "а вот к команде присоединится говнокодер Вася, и всё сломает", но я не хочу и не буду ради какого-то Васи писать менее органичный и красивый код.)
__________________
29375, 35
Последний раз редактировалось Aetae, 31.08.2021 в 21:25.
|
|
![Старый](/forum/images/ca_serenity/statusicon/post_old.gif)
31.08.2021, 21:45
|
![Аватар для Vlasenko Fedor](https://javascript.ru/forum/image.php?u=27064&dateline=1363177798) |
Профессор
|
|
Регистрация: 13.03.2013
Сообщений: 1,572
|
|
dc65k,
Ответь пожалуйста, для чего нужно подобное извращение?
|
|
|
|