工作踩坑之不准确的计时器setInterval

小小的吐槽

同事跑路了,刚刚接手这个模块我是崩溃的。这个定时刷新折线图数据的烂摊子我是真看不下去,奈何时间紧迫代码量大,也只能继续修修补补了。

我来描述下这个模块的几张echarts是如何糟糕的:

  1. 数据是分type取回来的,有的echarts图里要整合几种type的数据;
  2. 计时器不准确堵塞导致图表异常 -> 动态调整更新;
  3. 定时器最短更新时间为五秒,当你准时五秒去取数据时,可能取不到(设备还没来得及写入就去取数据) -> 取数据时前后偏移两个周期,都取回来比较补充,同时web显示的也不是最新的数据,而且延迟1-2个周期的;
  4. 调整设备时间后(2024年->2018年),设备回显数据时间跨度超过规定的两天,设备说数据按条数来限制而不是时间,底层代码不好修改 -> 前端遍历筛选;
  5. 设备读取数据库写入json,web获取时再去读,数据量大时接口慢 -> web的后端lua层分6次一次8h取数据,然后整合;

遭罪啊?!

回到正题-不准确的计时器 setInterval

为什么 setInterval 并不可靠

一般来说,setInterval 是一个常用的函数,用于按照指定的时间间隔重复执行指定的代码。虽然 setInterval 在许多情况下都可以正常工作,但是由于JavaScript 是单线程的,当某段代码执行时间超过了时间间隔,就会导致下一个计时器被推迟,这样会导致累积的延迟误差。

在这个模块中,这个现象异常明显,打开控制台查看网络,可以明显观察到,定时更新数据的计时器由于堵塞,会导致图标数据缺失。

为了掩盖数据缺失,他加上了自动连线,但是他还保留了smooth来维持线的顺滑,这就出现了曲线图里塞直线的独特风味。他真的,我哭死。

那该如何才能保证计时器的准确性

通过搜索可以了解到,可以使用requestAnimationFrame来保证计时器的准确性,但是对于这个模块并不适用。

虽然requestAnimationFrame可以确保在浏览器每一帧渲染之前执行指定的回调函数,但是它仍然会受到主线程执行其他任务的影响。当主线程中执行长时间任务时,例如接口请求、复杂计算或其他耗时操作,这些任务可能会延迟requestAnimationFrame的执行,从而影响到计时器的准确性。

所以,我只能采用setTimeout的递归执行,配合时间的动态调整来实现。

javascript 复制代码
    mounted(){
        // 执行轮询,用lastTime来存储时间
        this.lastTime = new Date().getTime();
        this.periodicPolling();
    },
    periodicPolling(){
        // 递归执行下一次计时
        var offset = new Date().getTime() - this.lastTime;
        this.timer = setTimeout(()=>{
            this.lastTime = new Date().getTime();
            // 这里执行更新操作
            this.refreshEchartsAllData();
            // 递归
            this.periodicPolling();
        }, this.customCycle*1000 - offset)
    },

通过以上代码,就可以自动计算更新时接口所耗费的时间,并动态调整定时刷新的时间,以免计时器被推迟累积,导致延迟误差。

说在最后

这个模块实在是棘手,各种设备导致的不准确来让web来承担和负责,前端的代码也是难以阅读和维护,也只能通过简单调整和修修补补,来堵住测试的嘴了。

相关推荐
梦帮科技8 小时前
GRAVIS v4.0:基于Web的极速套利架构设计与实时数据流实现
前端·人工智能·rust·自动化·区块链·智能合约·数字货币
爱勇宝9 小时前
办公资料反复修改、补传、交接混乱,我做了个桌面工具来解决这件事
前端·后端·程序员
微信开发api-视频号协议9 小时前
企业微信外部群开发自动化实践过程
java·前端·微信·自动化·企业微信·ipad
甲维斯9 小时前
Fable5:20美金的顶级设计师!
前端·人工智能
kyriewen10 小时前
我同时用了 Claude Code、Cursor 和 Codex,说说三个工具的真实差距——2026 年选错工具比不用 AI 更浪费时间
前端·ai编程·claude
Jackson__10 小时前
为了拯救我的腰椎和颈椎,我做了款浏览器插件!
前端·javascript·开源
闲猫10 小时前
Python FastAPI + SQLAlchemy 入门教程:从零搭建你的第一个 Web 应用
前端·python·fastapi
林小帅11 小时前
NestJS v11 + Prisma v7 ESM 迁移配置解析
前端·javascript·后端
IT_陈寒11 小时前
React的setState竟然不是立刻生效的,害我调试半天
前端·人工智能·后端
简简单单就是我_hehe11 小时前
前端埋点日志解决方案:完整 User-Agent 解析工具实现,爬虫识别、设备品牌、操作系统、浏览器版本全解析(附完整源码)
前端·爬虫