每秒刷新SVG运行数分钟后无法显示问题求助
问题描述
- 我是HTML、SVG、JavaScript等Web编程相关技术的新手,需要制作一个数据总览网页,展示设备采集到的各类信息。
- 我已经编写了Python脚本读取物理设备数据,脚本可以修改SVG文件中不同图形组件的
fill填充色属性,希望能把采集到的数据实时更新展示在网页上。 - 我使用的示例SVG文件内容如下:
<svg width="800" height="600" xmlns="http://www.w3.org/2000/svg"> <g id="Layer_1"> <title>Layer 1</title> <rect id="svg_1" height="386" width="527" y="94" x="150" stroke="#231F20" fill="yellow"/> <rect id="svg_2" height="386" width="527" y="114" x="450" stroke="#231F20" fill="yellow"/> </g> </svg>
- Python脚本会修改
id="svg_1"、id="svg_2"这类元素的fill属性,目前我用如下HTML文件展示SVG:
<!DOCTYPE html> <html> <head> <title>HTML SVG</title> </head> <body> <h1>Design</h1> <img id="demo" alt="" height="600" onload="javascript:(function() {setTimeout(function( {document.getElementById('demo').src=document.getElementById('demo').src.split('?' [0]+'?time='+new Date().getTime();},1000);}())" src="ee.svg" width="800" /> </body> </html>
- 上述JavaScript实现了每秒刷新一次SVG文件的逻辑,这个简易方案刚开始可以正常运行数分钟,但之后SVG就无法正常显示,需要可行的技术解决方案。
故障原因
现有方案跑久了失效,核心是两个问题:
- 刷新逻辑有缺陷:固定1秒无脑触发刷新,完全不判断上一次SVG是否加载完成。如果碰到Python正在写入SVG的瞬间发起请求,要么拿到写了一半的损坏文件,要么请求超时堆积,请求堆多了浏览器会直接拦截后续请求,自然无法正常显示。
- 每次全量重载SVG会持续占用浏览器缓存和内存,运行时间长了资源占满就会加载失败。
解决方案
给你两个从易到难的方案,新手可以直接选第一个落地。
方案1:修复现有逻辑(改动最小)
首先把写在标签属性里的零散JS抽离,加加载锁、预加载校验、错误重试逻辑,避免请求堆积和损坏内容渲染:
<!DOCTYPE html> <html> <head> <title>HTML SVG</title> </head> <body> <h1>Design</h1> <img id="demo" alt="" height="600" src="ee.svg" width="800" /> <script> const svgDom = document.getElementById('demo') let isLoading = false function refreshSvg() { // 上一次加载还没完成的话,直接跳过本轮刷新 if (isLoading) return isLoading = true // 用临时图片预加载,加载成功再替换正式src,避免显示损坏内容 const tempImg = new Image() tempImg.onload = () => { svgDom.src = tempImg.src isLoading = false // 加载成功后等1秒再触发下一轮刷新 setTimeout(refreshSvg, 1000) } tempImg.onerror = () => { isLoading = false // 加载失败的话等200毫秒重试,不要持续发请求打满队列 setTimeout(refreshSvg, 200) } tempImg.src = 'ee.svg?time=' + new Date().getTime() } // 页面首次加载完成后启动刷新循环 svgDom.onload = () => { setTimeout(refreshSvg, 1000) } </script> </body> </html>
同时要修改Python写SVG文件的逻辑:不要直接覆盖ee.svg,先把更新后的SVG内容写到临时文件(比如ee.svg.tmp),确认内容全部写入完成后,再把临时文件重命名为ee.svg。文件重命名是原子操作,可以保证网页请求SVG的时候永远拿到完整文件,不会读到半写入的损坏内容。
方案2:内联SVG+局部更新(长期运行最稳定)
不要用<img>标签加载外部SVG,直接把SVG代码内联写到HTML里,后续不用重载整个SVG文件:
- 把SVG内容直接写到HTML页面中,删掉原来的img标签
- Python端不用每次重写整个SVG文件,只需要输出一个简单的文本/JSON接口,返回类似
{"svg_1": "red", "svg_2": "green"}的结构,key是SVG元素ID,value是要设置的填充色 - 前端JS每秒请求一次这个轻量接口,拿到数据后直接修改对应SVG元素的
fill属性即可,请求体积极小,也不会出现文件损坏、资源占用过高的问题,可以长期稳定运行。
内容的提问来源于stack exchange,提问作者Marcin
相关产品推荐
相关产品推荐

