记一次使用setInterval(),定时器不准的问题

背景

在项目中,使用了setInterval()定时器函数实现一个倒计时的功能,并且倒计时的时长是可变的,当时长设置过大,并且在倒计时的过程中,切换浏览器,或者最小化,当再次返回的时候会出现定时器不准或者卡住的问题;

在网上看了很多文章:

  1. 首先受事件循环机制的原因,定时器设置的delay时间延迟没那么准确,这个还是比较好理解的;
  2. 第二点就是,看到有文章说浏览器tab切换,浏览器为了优化后台tab的加载损耗(以及降低耗电量),在未被激活的tab中定时器的最小延时限制为1S(1000ms),如果延时限制小于1S,也会出现不准的状况,这个我没有去尝试,因为我设置的时间间隔是1S;
  3. 然后就是浏览器最小化或者切换到后台运行时,时间长了之后浏览器的休眠机制,我觉得我的问题大概率就是这个原因造成的;

解决方案

网上提供的一些解决方案:

  1. 使用setTimeout()实现setInterval()的机制,我觉得我的问题点不在这;
  2. requestAnimationFrame,这个以后有时间看一下,目前不太了解;
  3. Web Worker:目前使用的是这种方式;

Web Worker

Web Worker 使得在一个独立于 Web 应用程序主执行线程的后台线程中运行脚本操作成为可能。这样做的好处是可以在独立线程中执行费时的处理任务,使主线程(通常是 UI 线程)的运行不会被阻塞/放慢。

实现一个定时器的基本操作:开启,暂停,重置,清除;并且我们是因为主线程中定时器不准才使用Worker的,所以我觉得重点是在正确的时间点告诉主线程即可,具体主线程要在定时器中做什么,那就让主线程在接受到消息的时候,自己去做就好了;

timeWorker.js:

js 复制代码
// 监听主线程的指令
let intervalId = null; 
let isRunning = false; 
let count = 0; 

let interval = '';
let countDown = 0;
let isRunning = false;
self.onmessage = (e) => {
  switch (e.data.action) {
    case 'start':
      startInterval();
      break;
    case 'pause':
      pauseInterval();
      break;
    case 'stop':
      clearInterval();
      break;
    case 'reset':
      resetInterval();
      break;
  }
};

// 开启
const startInterval = () => {
  if (!interval) {
    isRunning = true;
    interval = setInterval(() => {
      self.postMessage({ msg: '定时器开启~', count });
    }, 1000);
  }
};

// 暂停
const pauseInterval = () => {
  if (isRunning) {
    clearInterval(interval);
    isRunning = false;
  }
};
// 重置
const resetInterval = () => {
  clearInterval(interval);
  isRunning = false;
  count = 0;
  startInterval();
};
// 清除
const clearInterval = () => {
  clearInterval(interval);
  isRunning = false;
  count = 0;
};

主线程中在需要开启对定时器进行操作的地方进行即可;

js 复制代码
const worker = new Worker('./timeWorker.js');
// 接收消息
worker.onmessage = (e) => {
    // ...处理自己的业务逻辑
  console.log(e.data);
};

// 发消息
worker.postMessage({ action: 'start' });

先简单记录一下,以后有时间再详细记录;

相关推荐
进击的尘埃30 分钟前
SOLID 原则在 React 组件库里怎么落地:五个重构案例
javascript
忆江南35 分钟前
# iOS Block 深度解析
前端
米丘37 分钟前
vue-router v5.x 路由模式关于 createWebHistory、 createWebHashHistory的实现
前端
本末倒置18337 分钟前
Bun 内置模块全解析:告别第三方依赖,提升开发效率
前端·javascript·node.js
踩着两条虫38 分钟前
AI 驱动的 Vue3 应用开发平台 深入探究(二):核心概念之DSL模式与数据模型
前端·vue.js·ai编程
进击的尘埃39 分钟前
中介者模式:把面板之间的蜘蛛网拆干净
javascript
牛奶1 小时前
200 OK不是"成功"?HTTP状态码潜规则
前端·http·浏览器
Hilaku1 小时前
OpenClaw 很爆火,但没人敢聊它的权限安全🤷‍♂️
前端·javascript·程序员
ConardLi2 小时前
OpenClaw 完全指南:这可能是全网最新最全的系统化教程了!
前端·人工智能·后端
丁哥3 小时前
99.9%纯AI 做了一个ICO图标生成器(免费 全尺寸 不限文件大小)2ICO.CN欢迎品鉴
前端