setInterval倒计时切换页面后不准

news2024/12/23 9:49:59

背景

最近在做一个倒计时时,发现当切换浏览器tab后,再切回倒计时页面,倒计时的数据不准,比真正的剩余时间多,短时间还好,时间长了,计时器的误差会很大。

原因

倒计时是用setInterval每1000毫秒触发一次。

在进入页面时,计算剩余时间,把剩余时间用setInterval每1000毫秒触发一次进行减法。

但是由于浏览器的优化机制,为了更极致的优化,在切换tab之后浏览器会把setInterval的执行效率降低,在浏览器窗口非激活的状态下会停止工作或者以极慢的速度工作。那么这时候就不是1000毫秒减一次了,所以会有误差。

用setInterval实现计时

var start = new Date().getTime(), count = 0;
var interval = setInterval(function () {
    count++
    console.log(new Date().getTime() - (start + count * 1000) + 'ms')
    if(count == 10){
    clearInterval(interval);
    }
}, 1000)

image.png

可以看到,我打印的new Date().getTime() - (start + count * 1000) ,
也就是每次计时的误差,理想情况下,应该是0。

用setTimeout实现计时

var start = new Date().getTime(), count = 0,interval = 1000;
var timer = setTimeout(doFunc,interval);
function doFunc(){
    count++
    console.log(new Date().getTime() - (start + count * 1000) + 'ms');
  if(count < 10){
	    timer = setTimeout(doFunc,interval);
    }
}

image.png

也是一样的会出现误差

setInterval、setTimeout误差的不同之处

setInterval指定的是“开始执行”之间的间隔,并不考虑每次任务执行本身所消耗的时间。因此实际上,两次执行之间的间隔会小于指定的时间。比如,setInterval指定每 100ms 执行一次,每次执行需要 5ms,那么第一次执行结束后95毫秒,第二次执行就会开始。如果某次执行耗时特别长,比如需要105毫秒,那么它结束后,下一次执行就会立即开始。

为了确保两次执行之间有固定的间隔,可以不用setInterval,而是每次执行结束后,使用setTimeout指定下一次执行的具体时间。

模拟阻塞事件

setInterval

//阻塞代码
setInterval(function () {
  var n = 0
  while (n++ < 1000000000);
}, 1000)

var start = new Date().getTime(), count = 0;
var interval = setInterval(function () {
    count++
    console.log(new Date().getTime() - (start + count * 1000) + 'ms')
    if(count == 10){
    clearInterval(interval);
    }
}, 1000)

image.png

setTimeout

//阻塞代码
setInterval(function () {
  var n = 0
  while (n++ < 1000000000);
}, 1000)

var start = new Date().getTime(), count = 0,interval = 1000;
var timer = setTimeout(doFunc,interval);
function doFunc(){
    count++
    console.log(new Date().getTime() - (start + count * 1000) + 'ms');
  if(count < 10){
	    timer = setTimeout(doFunc,interval);
    }
}

image.png

可以看到加了一些阻塞线程的代码后,误差越来越严重,
在实际项目中,执行计时器的同时,会有很多其他异步阻塞事件,会导致倒计时功能不精确。

解决方案

1、setInterval每次触发的时候,重新计算剩余时间(误差在一分钟以内)

2、Web Workers(这个在nuxt中引入会报错,涉及到webpack改动较大,暂时不用)

3、进行误差修正,也就是获取到误差的值,并且根据这个误差值来动态调整我们执行回调的间隔时间

  • 计算误差值
  • 动态调整执行setTimeout的间隔

加上动态误差修正

var start = new Date().getTime(), count = 0,interval = 1000;
var offset = 0;//误差时间
var nextTime = interval - offset;//原本间隔时间 - 误差时间
var timer = setTimeout(doFunc,nextTime);
function doFunc(){
    count++
    console.log(new Date().getTime() - (start + count * interval) + 'ms');
     offset = new Date().getTime() - (start + count * interval);
    nextTime = interval - offset;
    if (nextTime < 0) { nextTime = 0; }
  if(count < 10){
	    timer = setTimeout(doFunc,nextTime);
    }
}

试试效果:

image.png

把每次的nextTime打印出来看看:

image.png

以看到每次的nextTime都会根据上次的误差值来动态调整,以尽量减少整体的误差。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1012729.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

盘点:人工智能发展趋势下的4大常见AI算法以及应用场景

近年来&#xff0c;人工智能的发展速度十分惊人&#xff0c;在安防监控、工业制造、农业、教育、金融、医疗等领域中的应用越来越广泛&#xff0c;并且未来几年也将继续保持高速的发展趋势。通过人工智能技术提高自动化程度、减少人工干预、提高监管效率&#xff0c;已经成为当…

在QML中如何使用首字母小写(蛇形)命名法

前言 最近在学习研究QML&#xff0c;想要自定义组件、信号、属性等&#xff0c;但如何对.qml文件、变量命名却是个问题。习惯了蛇形命名规范后&#xff0c;再让我回到驼峰命名规范&#xff0c;多少是不愿意的。 为了坚守信仰&#xff0c;我翻遍了各大技术网站&#xff0c;然而…

里氏替换原则~

里氏替换原则&#xff08;Liskov Substitution Principle&#xff09;是面向对象设计中的一个基本原则&#xff0c;它是由Barbara Liskov提出的。 如果对于每一个类型为Apple的对象1&#xff0c;都有类型为fruit的对象2&#xff0c;使得以fruit定义的所有程序 P 在所有的对象1都…

Web服务器解析:从基础到高级的全面指南

&#x1f482; 个人网站:【工具大全】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 引言 Web服务器是现代互…

竞赛选题 基于机器视觉的车道线检测

文章目录 1 前言2 先上成果3 车道线4 问题抽象(建立模型)5 帧掩码(Frame Mask)6 车道检测的图像预处理7 图像阈值化8 霍夫线变换9 实现车道检测9.1 帧掩码创建9.2 图像预处理9.2.1 图像阈值化9.2.2 霍夫线变换 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分…

el-calendar日历 简易排班

公司物流部要个简易的排班功能&#xff0c;由主管去设置线路&#xff0c;线路绑定上负责人。然后直接往日历里添加。 1、隐藏了自带的切换月份&#xff0c;改用了日期选择器。 2、禁用了非本月的点击事件&#xff0c;防止点击自动跳转到其他月份。 3、添加了点击多选&…

C# 流Stream详解(3)——FileStream源码

【FileStream】 构造函数 如果创建一个FileStream&#xff0c;常见的参数例如路径Path、操作方式FileMode、权限FileAccess。 这里说下FileShare和SafeFileHandle。 我们知道在读取文件时&#xff0c;通常会有两个诉求&#xff1a;一是如何更快的读取文件内容&#xff1b;二…

ATECLOUD二极管测试系统可以解决反向电流测试哪些痛点?

二极管具有单向导电性&#xff0c;但是有时候也会出现反向电流的情况。当反向电流变得很大时&#xff0c;二极管性能和寿命会受到很大影响。通过二极管测试系统对反向电流进行测试可以评估其性能和稳定性。 反向电流测试的重要性 理想情况下反向电流非常小&#xff0c;甚至可以…

2021年电工杯数学建模A题高铁牵引供电系统运行数据分析及等值建模求解全过程论文及程序

2021年电工杯数学建模 A题 高铁牵引供电系统运行数据分析及等值建模 原题再现&#xff1a; 我国是世界上电气化铁路运营里程最长、服役电力机车型号最多、运营最繁忙的国家。截至 2020 年底&#xff0c;我国铁路年消耗电量约 800 亿千瓦时&#xff0c;约占三峡年总发电量的 8…

Java实现添加文字水印、图片水印功能实战

java实现给图片添加水印实现步骤&#xff1a; 获取原图片对象信息&#xff08;本地图片或网络图片&#xff09; 添加水印&#xff08;设置水印颜色、字体、坐标等&#xff09; 处理输出目标图片 java实现给图片添加文字水印 获取原图片对象信息 第一步&#xff1a;获取需要…

人工智能安全-6-SQL注入检测

0 提纲 概述SQL注入方法SQL注入的检测方法SQL语句的特征提取天池AI上的实践 1 概述 SQLIA&#xff1a;SQL injection attack SQL 注入攻击是一个简单且被广泛理解的技术&#xff0c;它把 SQL 查询片段插入到 GET 或 POST 参数里提交到网络应用。 由于SQL数据库在Web应用中的…

【微服务实战之Docker容器】第四章-【微服务实战之Docker容器】第三章-镜像仓库

系列文章目录 【微服务实战之Docker容器】第一章-下载及安装 文章目录 系列文章目录坑&#xff1a;容器卷记得加入以下命令配置是个啥&#xff1f;能干啥&#xff1f;基本的命令读写规则映射添加说明卷的继承和共享 坑&#xff1a;容器卷记得加入以下命令配置 --privilegedtr…

van-calendar 实现移动端日历效果

<!--移动端端展示日历--><divv-if"isMobile &&tabActiveName true &&(formName 值班日历 || formName 值班编排)"><template v-if"Array.isArray(listData) && listData.length"><van-calendar:poppable&…

一生一芯14——chisel环境搭建

本人使用的ubuntu版本为22.04 anaconda 版本为23.1.0 本博客参考自https://blog.csdn.net/qq_38798111/article/details/129190615?ops_request_misc%257B%2522request%255Fid%2522%253A%2522169465704516800222836484%2522%252C%2522scm%2522%253A%252220140713.130102334…%…

芯科蓝牙BG27开发笔记8-片上Flash读写

目标 熟悉片上Flash的特点&#xff0c;知道如何使用&#xff0c;最好找到示例代码&#xff0c;有完整例程那是最好的 查找参考手册 除了768K的主空间&#xff0c;还包含&#xff1a; 1. USERDATA区域&#xff0c;用户定义数据&#xff0c;可以读写。大小只有1K。 2. 设备特…

长胜证券:十大流通股东占比例高好还是低好?

近年来&#xff0c;跟着我国本钱商场的不断发展&#xff0c;越来越多的投资者开始了解和关注股东占比这个目标。而在股东占比中&#xff0c;十大流转股东的持股份额是一个重要的目标。可是&#xff0c;关于投资者来说&#xff0c;十大流转股东占比是高好还是低好&#xff1f;本…

【SPI读取外部Flash】使用逻辑分析仪来读取FLASH Device ID

实验设备&#xff1a;25块钱的 逻辑分析仪 和 野火F429开发板 注意点&#xff0c;这个逻辑分析仪最大只能检测24M的波形&#xff0c;而SPI是在外部通道2&#xff0c;所以我们对系统时钟的分频&#xff0c;也就是给到通道2的时钟速度要在24M内&#xff0c;不然检测到的数据是有…

Peppertype.ai:人工智能内容营销平台

【产品介绍】 名称 Peppertype.ai 具体描述 Peppertype.ai是一个AI驱动的文章生成工具&#xff0c;可以帮助你在几秒钟内为各种渠道创建吸引人 的内容。无论你是想要写广告文案、社交媒体标题、博客大纲还是网站内容&#xff0c;Peppertype…

C++ PrimerPlus 复习 第五章 循环和关系表达式

第一章 命令编译链接文件 make文件 第二章 进入c 第三章 处理数据 第四章 复合类型 &#xff08;上&#xff09; 第四章 复合类型 &#xff08;下&#xff09; 第五章 循环和关系表达式 文章目录 for循环&#xff1b;基本语法重要问题和解答 基于范围的for循环&#xff08…

中秋学习Qt6

中秋学习Qt6 【1】Qt6 新增的模块【2】Qt6剔除模块和方法【3】Qt6改进 【1】Qt6 新增的模块 Qt6引入了一些新的模块&#xff0c;以便提供更多的功能和改进。以下是一些Qt6新增的模块&#xff1a; QtQuick3D&#xff1a;Qt6引入了全新的3D引擎模块QtQuick3D&#xff0c;它提供了…