从Firebase实时数据库读取数值数组,Plotly绘图失败求助
解决Plotly绘制Firebase实时数据库数值的问题
我一眼就瞅出问题所在了——你的analogval()函数里藏着异步操作的坑!Firebase的on('value')是异步回调,也就是说函数会直接返回,等数据从Firebase拉回来后才会执行回调里的代码。你直接调用analogval()的时候,根本拿不到返回的数值,Plotly当然画不出东西。而且你把on('value')放在定时函数里,还会重复创建监听,容易导致数据重复触发,反而添乱。
给你两种解决方案,看你需求选:
方案一:定时拉取数据(适合固定间隔更新的场景)
把数据获取改成单次请求,用async/await处理异步,确保拿到数据再传给Plotly:
<script src="plotly.min.js"></script> </head> <body> <script src="https://www.gstatic.com/firebasejs/7.2.0/firebase-app.js"></script> <script src="https://www.gstatic.com/firebasejs/7.2.0/firebase-analytics.js"></script> <script src="https://www.gstatic.com/firebasejs/7.2.1/firebase-auth.js"></script> <script src="https://www.gstatic.com/firebasejs/7.2.1/firebase-database.js"></script> <div class="navbar"><span>Analog Plotter by remidosol</span></div> <div class="wrapper"> <div id="chart"></div> <script src="FireConfig.js"></script> <script> // 先初始化一个空的折线图 Plotly.plot('chart', [{ y: [], type: 'line' }]); var cnt = 0; // 封装数据获取逻辑,返回Promise便于异步处理 function getAnalogData() { return databaseiot.orderByChild("analog").once('value') .then(dataSnapshot => { let arru = dataSnapshot.val().analog; // 处理数据成有效数字 arru = arru.toString().replace(/\\r/g,'').slice(1, 4); return Number(arru); }); } // 定时拉取数据并更新图表 setInterval(async () => { try { const value = await getAnalogData(); console.log('当前数值:', value); // 给图表添加新数据点 Plotly.extendTraces('chart', { y: [[value]] }, [0]); cnt++; // 超过300个点后,只显示最近300个 if (cnt > 300) { Plotly.relayout('chart', { xaxis: { range: [cnt - 300, cnt] } }); } } catch (err) { console.error('获取数据失败:', err); } }, 15); // 这里15ms间隔太密,建议改成100ms以上,避免性能问题 </script> </div> </body>
方案二:实时监听数据变化(适合数据主动推送的场景)
如果Firebase的数据是实时更新的,直接监听变化就行,不用定时拉取:
<script src="plotly.min.js"></script> </head> <body> <script src="https://www.gstatic.com/firebasejs/7.2.0/firebase-app.js"></script> <script src="https://www.gstatic.com/firebasejs/7.2.0/firebase-analytics.js"></script> <script src="https://www.gstatic.com/firebasejs/7.2.1/firebase-auth.js"></script> <script src="https://www.gstatic.com/firebasejs/7.2.1/firebase-database.js"></script> <div class="navbar"><span>Analog Plotter by remidosol</span></div> <div class="wrapper"> <div id="chart"></div> <script src="FireConfig.js"></script> <script> // 初始化空图表 Plotly.plot('chart', [{ y: [], type: 'line' }]); var cnt = 0; // 实时监听Firebase节点变化,数据更新就自动绘图 databaseiot.orderByChild("analog").on('value', dataSnapshot => { let arru = dataSnapshot.val().analog; arru = arru.toString().replace(/\\r/g,'').slice(1, 4); const value = Number(arru); console.log('实时更新数值:', value); Plotly.extendTraces('chart', { y: [[value]] }, [0]); cnt++; if (cnt > 300) { Plotly.relayout('chart', { xaxis: { range: [cnt - 300, cnt] } }); } }); </script> </div> </body>
额外提醒:
- 确认
databaseiot是正确指向你Firebase里的目标节点,别写错路径了。 - 检查控制台打印的
value是不是有效数字,如果是NaN,说明数据处理逻辑还要调整。 - 15ms的更新间隔真的太频繁了,浏览器和Firebase都可能扛不住,建议改成100ms以上,根据你的实际需求调整。
内容的提问来源于stack exchange,提问作者İbrahim
相关产品推荐
相关产品推荐

