如何实现准时的setTimeout

背景

setTimeout 是不准的。因为 setTimeout 是一个宏任务,它的指定时间指的是:进入主线程的时间。

setTimeout(callback, 进入主线程的时间)

所以什么时候可以执行 callback,需要看 主线程前面还有多少任务待执行

由此,才有了这个问题。

我们可以通过这个场景来进行演示:

图片

运行代码如下,通过一个计数器来记录每一次 setTimeout 的调用,而设定的间隔 * 计数次数,就等于理想状态下的延迟,通过以下例子来查看我们计时器的准确性

function timer() { var speed = 50, // 设定间隔 counter = 1,  // 计数 start = new Date().getTime(); function instance() { var ideal = (counter * speed), real = (new Date().getTime() - start); counter++; form.ideal.value = ideal; // 记录理想值 form.real.value = real;   // 记录真实值 var diff = (real - ideal); form.diff.value = diff;  // 差值 window.setTimeout(function() { instance(); }, speed); }; window.setTimeout(function() { instance(); }, speed); 
} 
timer(); 

而我们如果在 setTimeout 还未执行期间加入一些额外的代码逻辑,再来看看这个差值。

... 
window.setTimeout(function() { instance(); }, speed); 
for(var x=1, i=0; i<10000000; i++) { x *= (i + 1); } 
} 
... 

图片

可以看出,这大大加剧了误差。

可以看到随着时间的推移, setTimeout 实际执行的时间和理想的时间差值会越来越大,这就不是我们预期的样子。类比真实的场景,对于一些倒计时以及动画来说都会造成时间的偏差都是不理想的。

这站图可以很好的描述以上问题:

图片

如何实现准时的 “setTimeout”

requestAnimationFrame

window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。

该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行,回调函数执行次数通常是每秒60次,也就是每16.7ms 执行一次,但是并不一定保证为 16.7 ms。

我们也可以尝试一下将它来模拟 setTimeout。

// 模拟代码 
function setTimeout2 (cb, delay) { let startTime = Date.now() loop() function loop () { const now = Date.now() if (now - startTime >= delay) { cb(); return; } requestAnimationFrame(loop) } 
} 

图片

发现由于 16.7 ms 间隔执行,在使用间隔很小的定时器,很容易导致时间的不准确。

图片

再看看额外代码的引入效果。

... window.setInterval2(function () { instance(); }, speed); 
} 
for (var x = 1, i = 0; i < 10000000; i++) { x *= (i + 1); } 
... 

图片

略微加剧了误差的增加,因此这种方案仍然不是一种好的方案。

while

想得到准确的,我们第一反应就是如果我们能够主动去触发,获取到最开始的时间,以及不断去轮询当前时间,如果差值是预期的时间,那么这个定时器肯定是准确的,那么用 while 可以实现这个功能。

理解起来也很简单:

图片

代码如下:

function timer(time) { const startTime = Date.now(); while(true) { const now = Date.now(); if(now - startTime >= time) { console.log('误差', now - startTime - time); return; } } 
} 
timer(5000); 

打印:误差 0

显然这样的方式很精确,但是我们知道 js 是单线程运行,使用这样的方式强行霸占线程会使得页面进入卡死状态,这样的结果显然是不合适的。

setTimeout 系统时间补偿

这个方案是在 stackoverflow 看到的一个方案,我们来看看此方案和原方案的区别

原方案

图片

setTimeout系统时间补偿

图片

当每一次定时器执行时后,都去获取系统的时间来进行修正,虽然每次运行可能会有误差,但是通过系统时间对每次运行的修复,能够让后面每一次时间都得到一个补偿。

function timer() { var speed = 500, counter = 1,  start = new Date().getTime(); function instance() { var real = (counter * speed), ideal = (new Date().getTime() - start); counter++; var diff = (ideal - real); form.diff.value = diff; window.setTimeout(function() { instance(); }, (speed - diff)); // 通过系统时间进行修复 }; window.setTimeout(function() { instance(); }, speed); 
} 

图片

再来看看加入额外的代码逻辑的情况。

图片

依旧非常的稳定,因此通过系统的时间补偿,能够让我们的 setTimeout 变得更加准时,至此我们完成了如何让 setTimeout 准时的探索。

好了我们最后来总结一下4种方案的优缺点

while、Web Worker、requestAnimationFrame、setTimeout 系统时间补偿

图片

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

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

相关文章

MySQL8安装教程

MySQL安装教程 安装环境 Windows 10 软件下载 1、官网下载 官网可以下载最新版本的MySQL 8.0 下载地址&#xff1a; https://dev.mysql.com/downloads/windows/installer/8.0.html 开始安装 1、下载完成后&#xff0c;我们就开始安装&#xff0c;双击安装包&#xff0c…

李宏毅机器学习2023|图像生成模型

文章目录 图像生成Autoregressive&#xff08;各个击破&#xff09;Non-Autoregressive&#xff08;一次到位&#xff09;一次到位法额外的输入——从一个高维的Normal Distribution作simple得到一个向量常用的图片生成模型VAEFlow-based Generative ModelDiffusion ModelGAN D…

跨境电商独立站的6大模式,任你选择!

在几年前搭建跨境电商独立站和第三方平台基本上是同步发展起来的&#xff0c;但在后期的发展过程中&#xff0c;独立站经过不同时期的革新&#xff0c;形成了自己的模式。 当你准备好创建独立站的时候&#xff0c;首先你需要了解的就是独立站运营的模式类型&#xff0c;并找到最…

熟悉DHCP面临的安全威胁与防护机制

一个网络如果要正常地运行&#xff0c;则网络中的主机&#xff08;Host&#xff09;必需要知道某些重要的网络参数&#xff0c;如IP地址、网络掩码、网关地址、DNS服务器地址、网络打印机地址等等。显然&#xff0c;在每台主机上都采用手工方式来配置这些参数是非常困难的、或是…

C/S医院检验LIS系统源码

一、检验科LIS系统概述&#xff1a; LIS系统即实验室信息管理系统。LIS系统能实现临床检验信息化&#xff0c;检验科信息管理自动化。其主要功能是将检验科的实验仪器传出的检验数据经数据分析后&#xff0c;自动生成打印报告&#xff0c;通过网络存储在数据库中&#xff…

什么是数据资产化?数据怎样成为资产?怎样进入资产负债表?

财政部发布的《企业数据资源相关会计处理暂行规定》将从2024年1月1日起开始实施&#xff0c;为企业数据资源入表提供了基本指引&#xff0c;数据资产化有望迎来爆发期。什么是数据资产化&#xff0c;怎样让数据成为资产&#xff0c;成为了众多国有企业、上市公司关心的问题。 —…

JavaScript 中的双等号(==)和三等号(===)有何不同?何时使用它们?

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;JavaScript篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来JavaScript篇专栏内容:JavaScript-等号区别 目录 和 区别&#xff0c;分别在什么情况使用 一、等于操作符…

交换机端口镜像技术原理与配置

在网络维护的过程中会遇到需要对报文进行获取和分析的情况&#xff0c;比如怀疑有攻击报文&#xff0c;此时需要在不影响报文转发的情况下&#xff0c;对报文进行获取和分析。镜像技术可以在不影响报文正常处理流程的情况下&#xff0c;将镜像端口的报文复制一份到观察端口&…

掌握ElasticSearch(一):Elasticsearch安装与配置、Kibana安装

文章目录 〇、简介1.Elasticsearch简介2.典型业务场景3.数据采集工具4.名词解释 一、安装1.使用docker(1)创建虚拟网络(2)Elasticsearch安装步骤 2.使用压缩包 二、配置1.目录介绍2.配置文件介绍3.elasticsearch.yml节点配置4.jvm.options堆配置 二、可视化工具Kibana1.介绍2.安…

AI数字人互动大屏采用什么技术?

互动大屏&#xff08;技术支持&#xff1a;zhibo175&#xff09;本身具有令人瞩目的效果&#xff0c;再配置丰富多彩的多媒体&#xff0c;如引人注目的广告、特效或游戏等&#xff0c;可起到很好的引流作用。在空间开阔且客流密集的场所&#xff0c;使用各种形态的大面积屏幕&a…

轻量级开源服务器Tomcat本地部署并将网页发布到公网远程访问

目录 1.前言 2.本地Tomcat网页搭建 2.1 Tomcat安装 2.2 配置环境变量 2.3 环境配置 2.4 Tomcat运行测试 2.5 Cpolar安装和注册 3.本地网页发布 3.1.Cpolar云端设置 3.2 Cpolar本地设置 4.公网访问测试 5.结语 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通…

小型洗衣机哪个牌子质量好?口碑最好的四款小型洗衣机推荐

随着科技的快速发展&#xff0c;现在的人们越来越注重自己的卫生问题&#xff0c;不仅在吃上面会注重卫生问题&#xff0c;在用的上面也会更加严格要求&#xff0c;而衣服做为我们最贴身的东西&#xff0c;我们对它的要求也会更加高&#xff0c;所以最近这几年较火爆的无疑是内…

微信服务号变成订阅号全流程攻略

服务号和订阅号有什么区别&#xff1f;服务号转为订阅号有哪些作用&#xff1f;我们都知道&#xff0c;服务号一个月只能发4次文章&#xff0c;但是订阅号每天都能发文章。不过在接收消息这一方面&#xff0c;服务号群发的消息有消息提醒&#xff0c;并显示在对话框&#xff1b…

FC忍者神龟格斗可视化hack源码

[FC][忍者神龟格斗][最佳可视化][Final] 时间:2023.12.22 作者:FlameCyclone 内容: 1.可视化功能菜单 (1)菜单按键操作 1.上下键: 移动选项 2.左右键: 翻页 3.选择键: 翻转功能开关 4.开始键: 退出菜单 5.B键: 启用功能 …

143.【Nginx-02】

Nginx-02 (五)、Nginx负载均衡1.负载均衡概述2.负载均衡的原理及处理流程(1).负载均衡的作用 3.负载均衡常用的处理方式(1).用户手动选择(2).DNS轮询方式(3).四/七层负载均衡(4).Nginx七层负载均衡指令 ⭐(5).Nginx七层负载均衡的实现流程 ⭐ 4.负载均衡状态(1).down (停用)(2)…

小学班委有哪些职位

在成长的道路上&#xff0c;班委是一个不可或缺的角色。它不仅是一个职位&#xff0c;更是一份责任和担当。对于孩子们来说&#xff0c;成为班委不仅意味着荣誉&#xff0c;更意味着在集体中发挥自己的力量&#xff0c;为班级做贡献。 那么&#xff0c;小学班委有哪些职位呢&am…

配置Nginx出现403 (Forbidden)静态文件加载不出来

出现问题如图 出现此问题可能和索引文件缺失、访问限制等原因有关&#xff0c;在默认的Nginx的配置中&#xff0c;出现此问题的大概率问题可能出现在启动用户和nginx工作用户不一致所致。 Nginx的默认配置文件的 nginx.conf 里首行是 user www-data; 如果你是在 root 下启用…

基于JAVA实现的简易学生信息管理系统(附源码)

一、前言 最近在学习JAVA&#xff0c;这几天跟着网上的视频学完基础知识之后&#xff0c;做了一个学生信息管理系统&#xff0c;写的比较普通&#xff0c;没太大亮点&#xff0c;希望可以给初学者一些参考经验&#xff0c;另外&#xff0c;如有不恰当的地方还请各位指正&am…