@jeruthadam
Я крут

Как сделать таймаут в цикле Map?

Есть мап, мне нужно пройтись по нему и выполнить запросы, с периодичностью пару секунд. Но они все выполняются одновременно. Мне надо чтобы один за одним.

links.forEach(async b => {
    fetchDonor();
    await new Promise(r => setTimeout(r, randomInterval(1000, 2000)));
  });


Как затормозить цикли и ждать окончания выполнения одной операции и толко потом переходить к следущей?
  • Вопрос задан
  • 891 просмотр
Решения вопроса 1
lastuniverse
@lastuniverse
Всегда вокруг да около IT тем
я для похожих задач делал свой скромный костыль:
пример
// класс для очереди
class Queue{
	constructor(interval=1000) {
		this.list = [];
		setInterval(()=>{
			const item = this.list.shift();
			if( item && item.cb && typeof item.cb === "function" ){
				item.cb(...item.params);
			}
		},interval);
	}
	addTask(cb, ...params){
		this.list.push({cb:cb, params:params});
	}
}


// экземпляр класса для очеред. устанавливаем интервал срабатывания 2 секунды
const queue = new Queue(2000);

// links - ваш мап
links.forEach(b => {
	// хз как вы используете b, в вашем коде это не показано
	queue.addTask(()=>{
		// но вы вполне можете использовать ваше b тут
		fetchDonor();	
	});
});


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

PS: исправил опечатку в коде
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 3
Vlad_IT
@Vlad_IT Куратор тега JavaScript
Front-end разработчик
Это немного так не работает. forEach (как и map, reduce и.т.д.) так сказать синхронные функции, они не дожидаются выполнения переданной функции. Для такой задачи вам нужно либо писать на обычном цикле (for, while), либо использовать Promise.all
UPD: ой, невнимательно прочитал вопрос, вам нужно последовательно выполнить код над каждым элементом цикла links с задержкой между каждым элементом. Тут Promise.all вроде как не подойдет, но обычный for-in, for-of отлично подойдут.
Ответ написан
sergiks
@sergiks Куратор тега JavaScript
♬♬
Чтобы уважить требования одного API отправлять не более 3 запросов в секунду, я писал обертку, типа очереди задач. Задания хранятся в массиве. И сохраняются метки времени последних трёх запросов.
Перед исполнением очередного задания текущее время сравнивается с нулевым в массиве (если в массиве уже есть 3 отметки) и либо можно выполнять запрос, либо надо подождать – запускается таймаут на разницу времен.

Вам такого плана вариант нужен, или просто, чтобы один-за-другим, без ограничений по времени?
Ответ написан
BRAGA96
@BRAGA96
Вот как упрощенно выглядит нативный forEach и его асинхронная версия
function mySyncForEach(items, callback) {
    for (let i = 0; i < items.length; i++) {
        callback(items[i], i, items);
    }
}

async function myAsyncForEach(items, callback) {
    for (let i = 0; i < items.length; i++) {
        await callback(items[i], i, items);
    }
}
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы