Как синхронизировать таймеры обратного отсчета в нескольких вкладках браузера? - PullRequest
0 голосов
/ 15 октября 2018

Я разрабатываю приложение для React, в котором таймеры обратного отсчета являются основным компонентом (в то же время на странице может быть 10-20 таймеров).С сервера я получаю: как долго должен идти таймер и сколько осталось в секундах.Затем каждую секунду я рассказываю, сколько осталось.Исходные данные хранятся в редуксе и рассчитываются в локальном состоянии компонента.

Эти таймеры должны показывать одинаковые значения для каждого пользователя.

Проблема в том, что когда я дублирую вкладки в браузере , запрос API не происходит, соответственно,таймеры в новой вкладке возвращаются к старому состоянию.Мне кажется, что обновлять данные каждую секунду в Redux не лучший вариант, но других пока не вижу.

1 Ответ

0 голосов
/ 15 октября 2018

Вы сказали, что сервер отправляет вам оставшееся время в секундах.Таким образом, вы можете рассчитать на стороне клиента, когда обратный отсчет должен закончиться во время клиента.Вы можете хранить это в локальном хранилище.Когда открывается новая вкладка, вы можете использовать это значение для инициализации вашего таймера.

Это не требует, чтобы клиентское время было правильным или синхронизированным со временем сервера, поскольку все вкладки имеют одинаковое (возможно, неправильное) клиентское время.Вас интересует только разница в секундах между текущим временем клиента и временем клиента, которое вы сохранили для правильной инициализации вашего таймера.

Решение для его вычисления может выглядеть примерно так:

// when receiving the remaining seconds in the first tab

const onReceivedRemaining = (remaining) => {
    const now = new Date(); // current client time
    now.setSeconds(now.getSeconds() + remaining); // timer end in client time

    localStorage.set('elapsing', JSON.stringify(now));
}

// when initializing the timer in a second tab

const getInitial = () => {
    const elapsing_string = localStorage.get('elapsing');
    if (!elapsing_string) return null;

    const now = new Date();
    const elapsing = Date.parse(elapsing_string);
    return (elapsing - now) / 1000; // remaining time in seconds
}
...