#nodejs #async_await #backend
На этот вопрос уже даны ответы здесь: Как выполнить последовательно несколько асинхронных фунций в Javascript без коллбэков? (3 ответа) Закрыт 1 год назад. Пишу бекенд на node (v 8.11.4) Сервер общается с vk api. У vk есть ограничение - 5 запросов с секунду. Чтобы не уперется в ограничение было решено сделать функцию sleep: export default (ms) => { return new Promise(resolve => setTimeout(resolve, ms)); }; Далее есть мой метод (туда импортирую функцию sleep): app.post(path, (req, res) => { [1,2,3].map(async item => { await sleep(1000); console.log(item); }) }) Здесь я ожидаю что console.log будет срабатывать раз в секунду. Но этого не происходит. Проходит 1 секунда и console.log выводится 3 раза.
Ответы
Ответ 1
Все дело в том что этот код: [1,2,3].map(async item => { await sleep(1000); console.log(item); }) Тоже самое что и этот let foo = async item => { await sleep(1000); console.log(item); } foo(); foo(); foo(); Все три функции вызываются сразу. Каждая ждет по секунде и затем одна за другой выводят item в консоль. Так как начинают ждать они одновременно, то и заканчивают тоже, поэтому вы видите что сообщения выводятся сразу все. Можно сделать так: const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]; const foo = async (item, i) => { setTimeout(() => { return console.log(item); }, 1000 * i); // 1000 - это ваша задержка между вызовами } numbers.map(foo); Можно ставить устанавливать задержку после каждого вызова: const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]; const delayLoop = (array, delay) => { let i = 0; const loop = () => { setTimeout(() => { console.log(numbers[i]); if (++i < numbers.length) { loop(); } }, delay); }; loop(); } delayLoop(numbers, 1000); Можно сделать пример выше более универсальным, добавив callback: const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]; const delayLoop = (array, delay, handler) => { let i = 0; const loop = () => { setTimeout(() => { handler(numbers[i]); if (++i < numbers.length) { loop(); } }, delay); }; loop(); } const count = (value) => { console.log(`counter: ${value}`); } delayLoop(numbers, 1000, count);Ответ 2
Если я правильно понял инужно выводитьв консоль значения из массива с заданным интервалом, то можно сделать так - const sleep = (ms) => { return new Promise(resolve => setTimeout(resolve, ms)); }; const array = [1, 2, 3]; array.reduce(async(result, current) => result.then(() => sleep(1000).then(() => console.log(current))), Promise.resolve());Ответ 3
Возможно, такие циклы проще делать с помощью for..of циклов: app.post(path, async (req, res) => { for (const item of [1,2,3]) { await sleep(1000); console.log(item); }) })
Комментариев нет:
Отправить комментарий