document.hidden时暂停/恢复setInterval

时间:2019-01-10 12:38:27

标签: javascript

我需要每30秒显示一次警报。如果用户临时切换到其他选项卡,则计时器必须冻结。

我的代码如下:

var alertIntervalId = null
var quotes = ['quote1', 'quote2', 'quote3']
var NOTIFICATION_INTERVAL = 5
var TIMEOUT_IN_SECS = 5

var alertInterval = setInterval(function() {
    setTimeout(function() {
        randomIdx = Math.floor(Math.random() * quotes.length)
        alert(quotes[randomIdx])
    }, NOTIFICATION_INTERVAL * 1000)
}, TIMEOUT_IN_SECS * 1000)

function handleVisibilityChange(){
    if (document.hidden) {
        clearInterval(alertIntervalId)
        alertIntervalId = null
    } else {
      alertIntervalId = alertIntervalId || alertInterval()
    }
}

document.addEventListener("visibilitychange", handleVisibilityChange, false);
handleVisibilityChange()

但是代码不起作用(不会发生冻结),我不知道为什么。

P.S。我刚刚开始学习JavaScript,所以请考虑不要扔烂番茄。

修改

稍作重构后,代码看起来像

var alertIntervalId = null
var quotes = ['quote1', 'quote2', 'quote3']
var NOTIFICATION_INTERVAL = 5
var TIMEOUT_IN_SECS = 5

var alertInterval = function() {
  return setInterval(function() {
    setTimeout(function() {
      var randomIdx = Math.floor(Math.random() * quotes.length);
      alert(quotes[randomIdx])
    }, NOTIFICATION_INTERVAL * 1000)
  }, TIMEOUT_IN_SECS * 1000)
}

function handleVisibilityChange(){
    if (document.hidden) {
        clearInterval(alertIntervalId)
        alertIntervalId = null
    } else {
      alertIntervalId = alertIntervalId || alertInterval()
    }
}

document.addEventListener("visibilitychange", handleVisibilityChange, false);
handleVisibilityChange()

但是切换到其他标签后,警报仍然没有冻结:(

1 个答案:

答案 0 :(得分:1)

使用https://developer.mozilla.org/en-US/docs/Web/Events/visibilitychange检测用户何时单击其他选项卡,并在文档隐藏后冻结时间间隔,或者在文档可见时再次激活时间间隔。

按照书面规定,您永远不会知道文档何时被隐藏,因为它仅在您运行handleVisibilityChange()函数时才检查hidden属性。

所以我更喜欢使用事件侦听器和一个setInterval。

编辑:

问题是您的代码中有错误。打开控制台,查看alertInterval不是一个函数。由于您使用var alertInterval = setInterval(function() {},因此alertInterval实际上将是间隔的ID,而不是返回间隔的函数。因此将其更改为:

var alertInterval = function() {
  return setInterval(function() {
    setTimeout(function() {
        randomIdx = Math.floor(Math.random() * quotes.length)
        alert(quotes[randomIdx])
    }, NOTIFICATION_INTERVAL * 1000)
  }, TIMEOUT_IN_SECS * 1000);
};

以便它保留一个将返回新的时间间隔ID的函数。

我仍然没有弄清楚为什么同时使用setInterval()和setTimeout(),但这可能不在问题之列。

编辑2:

我一直在测试此代码,它在IE11和chrome中适用于我。

因此,请看看您的随机引号等。

var alertIntervalId = null;
var quotes = ['quote1', 'quote2', 'quote3'];
var NOTIFICATION_INTERVAL = 5;
var TIMEOUT_IN_SECS = 5;

var alertInterval = function() {
  return setInterval(function() {
    setTimeout(function() {
      var randomIdx = Math.floor(Math.random() * quotes.length);
      console.log(quotes[randomIdx]);
    }, NOTIFICATION_INTERVAL * 1000);
  }, TIMEOUT_IN_SECS * 1000);
};

function handleVisibilityChange(){
  if (document.hidden) {
    console.log( 'tab became hidden, clearing' );
    clearInterval(alertIntervalId)
    alertIntervalId = null;
  } else {
    console.log( 'tab became visible, restarting' );
    alertIntervalId = alertIntervalId || alertInterval();
  }
}

document.addEventListener("visibilitychange", handleVisibilityChange, false);
handleVisibilityChange();