Здравствуйте.
Мне нужно реализовать следующую логику:
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 а сама завершается.
Тут в примере пауза явно задаётся в цепи, но можно её значение просто например возвращать из самой лямбды.
Комментариев нет:
Отправить комментарий