Страницы

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

среда, 1 января 2020 г.

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

#javascript #setinterval #settimeout


Здравствуйте. 
Мне нужно реализовать следующую логику:  
  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. И не подобным "Войне и Миру" кодом.
    


Ответы

Ответ 1



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

Ответ 2



Как вариант - написать js функцию, которая в конце будет вызывать саму себя с setTimeout

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

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