JavaScript setTimeout与setInterval非激活状态速度限制

因为项目上用到WebSocket,并且后端有使用nginx转发,所以在前端用setTimeout做了心跳维持的递归间隔循环,防止nginx超时切断连接。

实际使用时,nginx超时时间设置的60s, 前端循环心跳是50s间隔,但是发现时不时就会因为nginx超时断开。

问题排查

该问题会出现在谷歌内核的浏览器中。

监控前端的WebSocket消息发送记录,发现在切换标签后,心跳间隔会变成51s,过了一会之后,间隔会进一步延长至60s。

因为消息发送需要时间,所以在切换标签之后,会在1~2轮心跳之后,nginx超时切断WebSocket连接。

问题测试

查找了网上的资料之后,初步推算问题应该是谷歌浏览器内核的优化导致的问题。

但是查到的资料都是以下说法:切换标签之后会进入非激活状态,setTimeout的最短间隔时间会变成1秒。

网上说法与我遇到的情况不同,于是自己做了下测试。

测试代码:

function sleep(millisecond) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve();
    }, millisecond);
  });
}

const logTime = async (sleepTime) => {
  const time = new Date().toTimeString().split(' ')[0];
  console.log('time:', time);
  await sleep(sleepTime * 1000);
  await logTime(sleepTime);
};

logTime(60);

测试结果(参数 5s):

time: 11:59:25
time: 11:59:30
// 切换标签
time: 11:59:36
time: 11:59:42
time: 11:59:48
// 回到页面
time: 11:59:57
// 最小化
time: 12:00:57
// 回到页面后立即执行了一次
time: 12:01:30
time: 12:01:35

测试结果(参数 60s):

time: 10:10:26
time: 10:11:26
// 浏览器切换标签
time: 10:12:27
time: 10:13:28
time: 10:14:29
// 浏览器最小化
time: 10:15:30
time: 10:16:31
time: 10:17:32
time: 10:18:33

测试结果(参数 70s):

time: 11:14:29
time: 11:15:39
time: 11:16:49
// 切换标签
time: 11:18:00
time: 11:19:11
time: 11:20:22
time: 11:21:33
// 最小化
time: 11:22:57
time: 11:24:57
time: 11:26:57

问题总结

由于谷歌浏览器内核优化,setTimeout会根据页面的状态,对延迟时间进行调整。

大致的延迟规则如下:

  1. 非当前标签最小化或休眠:等待时间向上取整分钟,如果设置时间就是整分钟的,+1s
    • 1s ~ 59s --> 60s
    • 60s --> 61s
    • 61s ~ 119s -> 120s
  2. 切换标签:延迟时间 +1s
  3. 回到页面时会根据计时时间判断执行,具体逻辑不清楚
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值