Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 31.08.2021, 13:25
Аспирант
Отправить личное сообщение для dc65k Посмотреть профиль Найти все сообщения от dc65k
 
Регистрация: 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);
    })
);
Ответить с цитированием
  #2 (permalink)  
Старый 31.08.2021, 15:37
Аватар для ksa
ksa ksa вне форума
CacheVar
Отправить личное сообщение для ksa Посмотреть профиль Найти все сообщения от ksa
 
Регистрация: 19.08.2010
Сообщений: 14,121

Сообщение от dc65k
то мы должны дождаться когда можно будет уменьшить очередь
И когда это наступает?
Ответить с цитированием
  #3 (permalink)  
Старый 31.08.2021, 15:47
Аспирант
Отправить личное сообщение для dc65k Посмотреть профиль Найти все сообщения от dc65k
 
Регистрация: 19.05.2020
Сообщений: 46

Очередь считается заполненной, когда ушло максимальное количество запросов (второй параметр). Очистить очередь на один запрос можно тогда, когда этот запрос выполнился.

Последний раз редактировалось dc65k, 31.08.2021 в 16:12.
Ответить с цитированием
  #4 (permalink)  
Старый 31.08.2021, 18:24
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,700

Может такой вариант
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.
Ответить с цитированием
  #5 (permalink)  
Старый 31.08.2021, 19:10
Аватар для ksa
ksa ksa вне форума
CacheVar
Отправить личное сообщение для ksa Посмотреть профиль Найти все сообщения от ksa
 
Регистрация: 19.08.2010
Сообщений: 14,121

Сообщение от dc65k
Очистить очередь на один запрос можно тогда, когда этот запрос выполнился.
Тогда и запускай следующий УРЛ... И так пока они не кончатся.
Ответить с цитированием
  #6 (permalink)  
Старый 31.08.2021, 20:20
Аватар для Aetae
Тлен
Отправить личное сообщение для Aetae Посмотреть профиль Найти все сообщения от Aetae
 
Регистрация: 02.01.2010
Сообщений: 6,491

Сообщение от 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.
Ответить с цитированием
  #7 (permalink)  
Старый 31.08.2021, 20:36
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,700

Сообщение от Aetae
Зачема так усложнять? Есть же классика:
const responses = new Array(requests.length);
Классика - не значит хорошо.
В данном случае, конечно без разницы, но я так не делаю
new Array(n) создает "дырявый" массив, который очень неэффективен при всяких оптимизациях.
Ответить с цитированием
  #8 (permalink)  
Старый 31.08.2021, 20:41
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,700

Сообщение от 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.
Ответить с цитированием
  #9 (permalink)  
Старый 31.08.2021, 20:55
Аватар для Aetae
Тлен
Отправить личное сообщение для Aetae Посмотреть профиль Найти все сообщения от Aetae
 
Регистрация: 02.01.2010
Сообщений: 6,491

voraa, да согласен, тупанул.)

По поводу new Array - я его использую только именно в таком случае и ни в каком ином. Считаю что использовать подходящие инструменты в подходящих местах - стоит, а откидывать те или иные вещи скопом только потому, что в некоторых ситуациях(прекрасно известных) они могут привести к неприятным последствиями, ограничивая себя узкими рамками "безопасного" кода - не стоит.)

Обычно всё это сводится к "а вот к команде присоединится говнокодер Вася, и всё сломает", но я не хочу и не буду ради какого-то Васи писать менее органичный и красивый код.)
__________________
29375, 35

Последний раз редактировалось Aetae, 31.08.2021 в 21:25.
Ответить с цитированием
  #10 (permalink)  
Старый 31.08.2021, 21:45
Аватар для Vlasenko Fedor
Профессор
Отправить личное сообщение для Vlasenko Fedor Посмотреть профиль Найти все сообщения от Vlasenko Fedor
 
Регистрация: 13.03.2013
Сообщений: 1,572

dc65k,
Ответь пожалуйста, для чего нужно подобное извращение?
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как реализовать отправку содержимого из iframe нажатием комбинации клавиш ctrl+enter Naizer Общие вопросы Javascript 4 27.11.2013 17:39
Подскажите как реализовать такую задачу Gasherez (X)HTML/CSS 0 20.09.2013 19:59
Управление скроллом "а-ля тач" HonesT Элементы интерфейса 2 27.08.2013 14:25
Как это реализовать на JS Bezlyj Общие вопросы Javascript 6 06.03.2012 09:20
Как реализовать? Fliand Элементы интерфейса 4 22.08.2009 19:47