我正在使用useEffect react钩子设置倒计时变量的间隔。我注意到,当浏览器中的选项卡未激活时,内部停止工作。如果该选项卡处于活动状态,则代码将完全按预期工作。
有更好的方法吗?下面是代码示例。
export default function CountdownTimer({ minutes_left, action }) {
const [timeLeft, setTimeLeft] = useState();
function updateTimer() {
const remaining = ...work out time left
setTimeLeft(remaining);
}
useEffect(() => {
const interval = setInterval(() => {
updateTimer();
if (timeLeft.asMilliseconds() <= 0) {
action();
clearInterval(interval);
}
}, 1000);
return () => clearInterval(interval);
}, []);
return (
<p>{timeLeft}</p>
);
}
我已经在Dan Abramov的帖子here中实现了有关此问题的解决方案。但是,当选项卡处于非活动状态时,Dan的解决方案也不会呈现。
答案 0 :(得分:0)
请注意,这就是浏览器的工作方式:不活动的选项卡被取消优先级,计时器受到严重限制。请记住,php_sqlsrv_7_nts_x86
和setTimeout
最明显地是不是“在X毫秒过去之后运行代码”,它们是“至少在之后 X运行代码。 ms过去了”,但不能保证事情不会真正发生,因为调度(例如,选项卡是否处于活动状态,甚至在OS可以通知浏览器的范围内是可见的)以后,甚至仅仅是因为一些JS代码需要花费比指定的时间间隔更长的时间才能完成,因此从字面上看,您的超时直到完成后才能触发(因为JS是单线程的)。
对于Firefox,请参见https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API#Policies_in_place_to_aid_background_page_performance,了解如何在计时器上执行节流;对于Chrome,请参见https://developers.google.com/web/updates/2017/03/background_tabs
(对于任何其他浏览器,网络搜索都应该为您找到类似的文档。)
但是,请考虑一下使选项卡成为后台进程的含义:如果您的用户看不到您的选项卡,为什么您根本需要更新任何内容?您的用户将无法看到这些更新。相反,可以考虑在选项卡变得不可见时挂起纯视觉任务,然后在选项卡再次变得可见时恢复它们,并使用时钟检查来确定“是否需要发生”。
实际上,如果您使用setInterval
或setInterval
,即使在前台选项卡上也很重要:10个连续的setTimeout
不会 暗示它“一旦完成,将精确到1秒,这意味着我们完成后至少要 1秒钟,但是我们可以很容易地在7号或7号之前达到“一秒钟后”的标记。因为JS是单线程的,所以会触发第8个超时,并且如果某些任务花费了一段时间,则直到该任务完成后才会激发您的超时。因此,您至少要为此更新代码。
答案 1 :(得分:-1)
可能是因为useEffect调用在第一个渲染之后使用clearInterval函数。这是useEffect
的清理与返回的函数Example Using Hooks一起工作的方式。