记一次使用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' });

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

相关推荐
开发者小天20 分钟前
为什么 /deep/ 现在不推荐使用?
前端·javascript·node.js
如白驹过隙1 小时前
cloudflare缓存配置
前端·缓存
excel1 小时前
JavaScript 异步编程全解析:Promise、Async/Await 与进阶技巧
前端
Jerry说前后端1 小时前
Android 组件封装实践:从解耦到架构演进
android·前端·架构
步行cgn2 小时前
在 HTML 表单中,name 和 value 属性在 GET 和 POST 请求中的对应关系如下:
前端·hive·html
hrrrrb2 小时前
【Java Web 快速入门】十一、Spring Boot 原理
java·前端·spring boot
找不到工作的菜鸟2 小时前
Three.js三大组件:场景(Scene)、相机(Camera)、渲染器(Renderer)
前端·javascript·html
定栓2 小时前
vue3入门-v-model、ref和reactive讲解
前端·javascript·vue.js
专注API从业者2 小时前
基于 Flink 的淘宝实时数据管道设计:商品详情流式处理与异构存储
大数据·前端·数据库·数据挖掘·flink
龙在天2 小时前
H5开发,开发照相机,以及组件封装
前端