Как реализовать задачу с одновременными запросами на сервер?
Всем привет. Есть функция, она принимает на вход массив адресов на которые будет происходить запрос и количество максимальных запросов (количество максимальных запросов в очереди). Если количество запросов больше чем второй параметр (очередь заполнена), то мы должны дождаться когда можно будет уменьшить очередь и продолжить делать следующие запросы по описанному принципу заполнения очереди.
Ниже я написал начало решения, вопрос именно в том как в коде написать очистку очереди и продолжение выполнение запросов? 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); }) ); |
Цитата:
|
Очередь считается заполненной, когда ушло максимальное количество запросов (второй параметр). Очистить очередь на один запрос можно тогда, когда этот запрос выполнился.
|
Может такой вариант
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); }) ); |
Цитата:
|
Цитата:
const responses = new Array(requests.length); P.S. И да, работать как требует dc65k оно не будет: осле первых трёх количество запросов будет нарастать без контроля, а должно быть всегда три.) |
Цитата:
В данном случае, конечно без разницы, но я так не делаю new Array(n) создает "дырявый" массив, который очень неэффективен при всяких оптимизациях. |
Цитата:
<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, да согласен, тупанул.)
По поводу new Array - я его использую только именно в таком случае и ни в каком ином. Считаю что использовать подходящие инструменты в подходящих местах - стоит, а откидывать те или иные вещи скопом только потому, что в некоторых ситуациях(прекрасно известных) они могут привести к неприятным последствиями, ограничивая себя узкими рамками "безопасного" кода - не стоит.) Обычно всё это сводится к "а вот к команде присоединится говнокодер Вася, и всё сломает", но я не хочу и не буду ради какого-то Васи писать менее органичный и красивый код.) |
dc65k,
Ответь пожалуйста, для чего нужно подобное извращение? |
Часовой пояс GMT +3, время: 10:58. |