【问题标题】:How to synchronize countdown timers in multiple browser tabs?如何在多个浏览器选项卡中同步倒数计时器?
【发布时间】:2019-03-19 15:52:08
【问题描述】:

我正在 React 上开发一个应用程序,其中 倒数计时器 是主要组件(同时页面上可以有 10-20 个计时器)。从服务器我得到:计时器应该走多长时间以及以秒为单位还剩下多少。然后每一秒我都会重新计算还剩下多少。源数据存储在 redux 中,并在组件本地状态中计算。

这些计时器应该为每个用户显示相同的值。

问题是当我复制浏览器中的选项卡时,没有发生api请求,分别是新选项卡中的计时器回滚到旧状态。 在 redux 中每秒更新数据对我来说似乎不是最好的选择,但我还没有看到其他选项。

【问题讨论】:

  • 每秒更新您的商店完全没有问题。但无论如何,我看不出这如何解决你的问题。每个选项卡都有自己的上下文和自己的 redux 存储。您可以做的是将结束时间存储在本地存储中,并在初始化计时器时读取该值。
  • 我考虑过这个选项。但是这样我应该使用当前客户端时间,这可能与服务器时间不同。
  • 如果您根据服务器发送的内容计算客户端的结束时间并存储该值,这并不重要。这也是时区信息的用途。
  • 可以,但用户可以手动设置分钟和秒数。
  • 但是,如果您完全根据客户端时间计算结束时间,为什么这很重要。如果用户出于某种原因这样做,则每个选项卡中的时间仍然相同(错误)。

标签: reactjs timer redux browser-tab


【解决方案1】:

您说服务器以秒为单位向您发送剩余时间。因此,您可以在客户端计算倒计时应该在客户端时间结束的时间。您可以将其存储在本地存储中。当打开一个新选项卡时,您可以使用该值来初始化您的计时器。

它不需要客户端时间正确或与服务器时间同步,因为所有选项卡共享相同(可能是错误的)客户端时间。您只关心当前客户端时间与您为正确初始化计时器而保存的客户端时间之间的秒差。

计算它的解决方案大致如下所示:

// 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
}

【讨论】:

  • 以这种方式不断保存一组计时器是否可以出于性能原因?
  • @gooner_dp 您可以将剩余的秒数保留在 redux 存储中并定期更新。那完全没问题。但我会避免不必要地读写 localStorage。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-09
  • 1970-01-01
  • 1970-01-01
  • 2012-03-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多