【问题标题】:change setInterval timings from within the interval从间隔内更改 setInterval 时间
【发布时间】:2021-05-27 04:11:06
【问题描述】:

我想根据浏览器中是否处于活动状态来更新页面上的数据。这仅适用于针对 document.hasFocus() 的 if 查询。

但我现在还想要的是,当焦点回到页面时,会立即或至少在 5 秒内发生更新,然后通常在 30 秒后再次发生。

我现在的想法是在区间内改变区间时间。但是,我无法做到这一点。

  useEffect(() => {
    const statusRefreshInterval = setInterval(() => {
      if (document.hasFocus()) {
        console.log("hasFocus:", new Date().toLocaleTimeString());
        setInterval(statusRefreshInterval, 30000);
      } else {
        console.log("hasNoFocus:", new Date().toLocaleTimeString());
        setInterval(statusRefreshInterval, 5000);
      }
    }, 30000);
    return () => clearInterval(statusRefreshInterval);
  }, []);

编辑: 这样,我就满足了我的所有要求:

  var lastUpdate = useRef();  // needed to use variables inside useEffect
  const allowedUpdatesAfterSec = 300;
  useEffect(() => {
    // initial update
    lastUpdate.current = Date.now() / 1000;

    // update when website gets focus again
    window.addEventListener("focus", function () {
      if (Date.now() / 1000 - lastUpdate.current > allowedUpdatesAfterSec) {
        console.log("EventListenerUpdate:", new Date().toLocaleTimeString());
        lastUpdate.current = Date.now() / 1000;
      }
    });

    // update every allowedUpdatesAfterSec when website is active
    const updateRefreshInterval = setInterval(() => {
      if (Date.now() / 1000 - lastUpdate.current > allowedUpdatesAfterSec) {
        if (document.hasFocus()) {
          console.log("IntervalUpdate:", new Date().toLocaleTimeString());
          lastUpdate.current = Date.now() / 1000;
        }
      }
    }, 60000);
    return () => clearInterval(updateRefreshInterval);
  }, []);

我会考虑改用 setTimeout 而不是 setInterval。

【问题讨论】:

  • 您的意思是用新值更改间隔“内”或下一个间隔之前的间隔?您对每个都有硬编码值,但也许一个参数是您想要/需要的? stackoverflow.com/q/109086/125981
  • “焦点回到页面”焦点事件没有冒泡,所以也许你需要为那个事件添加一个事件处理程序然后处理developer.mozilla.org/en-US/docs/Web/API/Element/focus_event
  • 我会考虑使用 setTimeout 而不是冒着堆积 setIntervals 的风险——只是为了安全起见。

标签: javascript reactjs setinterval


【解决方案1】:

您可以从 setTimeout 回调中递归调用 setTimeout 并使用动态时间,例如-

let timeToCall = 1000
let seconds = Date.now()/1000
function dynamicTimeoutFunction() {
  console.log(`I was called after ${Date.now()/1000 - seconds} seconds`)
  timeToCall += 1000
  setTimeout(dynamicTimeoutFunction, timeToCall)
}

setTimeout(dynamicTimeoutFunction, timeToCall)

【讨论】:

    【解决方案2】:

    您只是通过这种方式创建更多间隔,因为您是从 setInterval 中调用 setInterval。我只需将 setInterval 更改为 setTimeout。

      useEffect(() => {
        const statusRefreshInterval = setTimeout(() => {
          if (document.hasFocus()) {
            console.log("hasFocus:", new Date().toLocaleTimeString());
            setTimeout(statusRefreshInterval, 30000);
          } else {
            console.log("hasNoFocus:", new Date().toLocaleTimeString());
            setTimeout(statusRefreshInterval, 5000);
          }
        }, 30000);
        return () => clearTimeout(statusRefreshInterval);
      }, []);
    

    这样您就可以为下一次通话设置新时间。

    【讨论】:

      猜你喜欢
      • 2010-11-19
      • 2013-02-12
      • 2016-05-28
      • 1970-01-01
      • 1970-01-01
      • 2011-11-23
      • 1970-01-01
      • 2019-12-23
      • 1970-01-01
      相关资源
      最近更新 更多