Страницы

Поиск по вопросам

среда, 9 января 2019 г.

Повторение кода через разные промежутки времени Javascript

Здравствуйте. Мне нужно реализовать следующую логику: 1 этап: пользователи что-то делают на сервере - 40 секунд 2 этап: выполняется процесс - случайное кол-во секунд (от 3 до 10) 3 этап: кулдаун - пользователи любуются результатом - 2 секунды и все повторяется с начала и так вечно
setInterval не подходит, так как в нем код повторяется через РАВНЫЕ промежутки времени, а время окончания работы моего кода становится известно только в процессе. Если же использовать время интервала с запасом, то 3 этап будет выполняться то 2 секунды, то 15 - неприемлемо.
Такое решение (рекурсия)
function round() { var delay = 20000 * Math.random(); //узнаем, через сколько в этот раз должен сработать код setTimeout(function () { console.log('Hellow world!');//что-то тут делаю round(); //и перезапускаю }, delay); } round();
не подойдет, так как при каждой новой рекурсии будут накапливаться временные переменные и будет забиваться память, а перезагружать сервер постоянно не получится
явно ведь должно быть красивое и правильное решение? что в таком случае использовать? Нужно сделать так, чтобы была какая-то асинхронная функция с примерно таким содержанием:
-сообщить о начале 1 этапа (использую socket.io) -ждать 40 секунд -сообщить о начале 2 этапа -ждать случайное кол-во секунд -сообщить о начале третьего -ждать 2 секунды
потом функция должна запуститься заново но не рекурсией. И хотелось бы без вложенных друг в друга setTimeout. И не подобным "Войне и Миру" кодом.


Ответ

Вложеные setTimeout стек не забивают, так как выполняются асинхронно, их бояться не надо.
Для решения вашей ситуации вам надо написать самому какую-то timing микро библиотеку, позволяющую создавать цепи событий с таймаутами. Это что-то типа промисов в fetch.
Выглядеть этот код будет примерно так
TimeoutChain.PlusOne(() => { /*...*/ },2000) .PlusOne(() => { /* ещё код*/ },3000).StartChain();
Реализация будет на основе setTimeout. Но это будет выглядеть красиво, так как она инкапсулирована в эту функцию, так же из-за её асинхронности стек она не будет забивать. Так как каждая функция вызывает свой setTimeout а сама завершается.
Тут в примере пауза явно задаётся в цепи, но можно её значение просто например возвращать из самой лямбды.

Комментариев нет:

Отправить комментарий