you_are_enot
@you_are_enot
Пограммист любитель

Как объединить два асинхронных цикла?

У меня есть массив рассылки содержащий массивы пользователей, которым нужно отправить сообщения. Между отправкой сообщений должен быть интервал 50мс. Как реализовать подобный "двойной" асинхронный цикл?

for (const list of lists) {

    for (const user of list) {

        // Задержка 50 мс
        setTimeout(() => {
            sendMessage(user);
        }, 50);

    };
};
  • Вопрос задан
  • 191 просмотр
Пригласить эксперта
Ответы на вопрос 3
lastuniverse
@lastuniverse
Всегда вокруг да около IT тем
ну можно что-то типа очереди организовать, скрещенной с менеджером задач. Например так (очень примитивно, но задачу решает)

class MessageManager {
   constructor (interval){
      this.list = [];
      setInterval(()=>{
          this.next();
      }, interval);
   }
   message(handler) {
      this.list.push(handler);
   }
   next(){
      if(!this.list.length)
         return;
      let handler = this.list.shift();
      handler();
   }
}

var msgmgr = new MessageManager(50);

for (const list of lists) {

    for (let user of list) {

        msgmgr.message(() => {
            sendMessage(user);
        });
    };
};
Ответ написан
@lazalu68
Suspended ))
Можно пользоваться async/await. С одной стороны конечно хорошо бы все же сделать плоский массив пользователей, но если условия позволяют, то можно забить на это:

function delay(timeout) {
	return new Promise(res => setTimeout(res, timeout));
}

async function sendMessage(user, message) {
	/* example */
	console.log(user, message);
	/* example */
}

async function sendAllTheMessagesToOurLovelyUsers(mailing_data, delay_between_requests) {
	for (let mailing_entry of Object.values(mailing_data)) {
		for (let user of mailing_entry.users) {
			await sendMessage(user, mailing_entry.msg);
			await delay(delay_between_requests);			
		}
	}
};

sendAllTheMessagesToOurLovelyUsers([
	{
		users: [
			{ user_id: 25 },
			{ user_id: 14 },
		],
		msg: "message1"
	}, 
	{
		users: [
			{ user_id: 14 },
			{ user_id: 6 }
		],
		msg: "message2"
	}
], 500);


Старый ответ

Можно ведь из массива массивов пользователей сделать один массив и пользоваться async/await:
function delay(timeout) {
	return new Promise(res => setTimeout(res, timeout));
}

async function sendMessage(user) {
	/* example */
	console.log(user);
	/* example */
}

async function sendAllTheMessagesToOurLovelyUsers(user_lists, delay_between_requests) {
	const users = {};

	for (let user of user_lists.flat()) {
		/* пример процедуры получения массива уникальных пользователей */
		if (!(users[ user.user_id ] in users)) {
			users[ user.user_id ] = user;
		}
	}

	for (let user of Object.values(users)) {
		await sendMessage(user);
		await delay(delay_between_requests);
	}	
};

sendAllTheMessagesToOurLovelyUsers([
	[
		{ user_id: 25 },
		{ user_id: 14 },
	],
	[
		{ user_id: 14 },
		{ user_id: 6 }
	]
], 500);

Ответ написан
Если нужно дождаться отправки предыдущего сообщения
https://developer.mozilla.org/uk/docs/Web/JavaScri...
+ Promise или fetch если отправляете http запросом
Ответ написан
Ваш ответ на вопрос

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

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