如何在多个浏览器选项卡中同步倒数计时器?
How to synchronize countdown timers in multiple browser tabs?
我正在 React 上开发一个应用程序,其中 倒数计时器 是主要组件(同时页面上可以有 10-20 个计时器)。从服务器我得到:计时器应该走多长时间以及以秒为单位还剩多少。然后每一秒我都会重新计算还剩下多少。源数据存储在 redux 中,并在组件本地状态中计算。
这些计时器应该为每个用户显示相同的值。
问题是当我在浏览器中复制标签时,api请求没有发生,新标签中的计时器回滚到旧状态。
在 redux 中每秒更新数据在我看来不是最好的选择,但我还没有看到其他人。
您说服务器以秒为单位向您发送剩余时间。因此,您可以在客户端计算倒计时应该在客户端时间结束的时间。您可以将其存储在本地存储中。打开新选项卡时,您可以使用该值来初始化计时器。
它不需要客户端时间正确或与服务器时间同步,因为所有选项卡共享相同的(可能是错误的)客户端时间。您只对当前客户端时间与您为正确初始化计时器而保存的客户端时间之间的秒数差异感兴趣。
计算它的解决方案大致如下所示:
// 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
}
我正在 React 上开发一个应用程序,其中 倒数计时器 是主要组件(同时页面上可以有 10-20 个计时器)。从服务器我得到:计时器应该走多长时间以及以秒为单位还剩多少。然后每一秒我都会重新计算还剩下多少。源数据存储在 redux 中,并在组件本地状态中计算。
这些计时器应该为每个用户显示相同的值。
问题是当我在浏览器中复制标签时,api请求没有发生,新标签中的计时器回滚到旧状态。 在 redux 中每秒更新数据在我看来不是最好的选择,但我还没有看到其他人。
您说服务器以秒为单位向您发送剩余时间。因此,您可以在客户端计算倒计时应该在客户端时间结束的时间。您可以将其存储在本地存储中。打开新选项卡时,您可以使用该值来初始化计时器。
它不需要客户端时间正确或与服务器时间同步,因为所有选项卡共享相同的(可能是错误的)客户端时间。您只对当前客户端时间与您为正确初始化计时器而保存的客户端时间之间的秒数差异感兴趣。
计算它的解决方案大致如下所示:
// 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
}