Firebase实时数据库页面刷新时Numeroalertas重复自增问题求助
问题:Normal区间刷新页面时Numeroalertas错误自增
我编写了一段读取Firebase实时数据库温度数据的代码,将温度划分为「Normal :)」「Risco :|&」「Falha :(&」三个区间。当温度从Normal进入Risco或Falha区间时,数据库的Numeroalertas字段会自动加1,这部分功能正常,但处于Normal区间时刷新页面,Numeroalertas会莫名自增1,原代码如下:
var lastTemperature; var alertTriggered = false; // Retrieve the last temperature and alert state from the database when the page loads var estufaRef = firebase.database().ref("Estufas/Estufa Nike/Dados"); estufaRef.once("value").then(function(snapshot) { var data = snapshot.val(); if (data && data.UltimaTemperatura !== undefined) { lastTemperature = data.UltimaTemperatura; // Only update alertTriggered if it was false before if (alertTriggered === false) { alertTriggered = data.AlertaAtivado || false; } } // Check if Numeroalertas has already been incremented in this session var alreadyIncremented = localStorage.getItem("alreadyIncremented") || false; if (alertTriggered && !alreadyIncremented) { updateAlertState(true); localStorage.setItem("alreadyIncremented", true); } }); // Update the alert state in the database when the temperature enters or leaves the "Risco :|" zone function updateAlertState(alertState) { var estufaRef = firebase.database().ref("Estufas/Estufa Nike/Dados"); estufaRef.once("value").then(function(snapshot) { var data = snapshot.val(); if (data && data.AlertaAtivado !== undefined && data.AlertaAtivado !== alertState) { var newNumeroAlertas = data.Numeroalertas || 0; if (alertState) { newNumeroAlertas++; } estufaRef.update({ AlertaAtivado: alertState, Numeroalertas: newNumeroAlertas }); // Set the alreadyIncremented flag to true localStorage.setItem("alreadyIncremented", true); } else { estufaRef.update({ AlertaAtivado: alertState }); } }); } function atualizaTemperatura() { var currentTemperature = temperaturaArray[temperaturaArray.length - 1].temperatura; document.getElementById("temperaturaatual").innerHTML = currentTemperature; var zonaAtual = document.getElementById("zonaatual"); if (currentTemperature <= 50) { zonaAtual.innerHTML = "Normal :)"; zonaAtual.style.color = "green"; if (alertTriggered) { alertTriggered = false; updateAlertState(false); } } else if (currentTemperature > 50 && currentTemperature <= 100) { if (currentTemperature !== lastTemperature && currentTemperature > lastTemperature && !alertTriggered) { // Only trigger alert if the current temperature is greater than the last temperature recorded and the alert has not already been triggered zonaAtual.innerHTML = "Risco :|&"; zonaAtual.style.color = "orange"; alertTriggered = true; updateAlertState(true); } else { zonaAtual.innerHTML = "Risco :|&"; zonaAtual.style.color = "orange"; if (alertTriggered) { alertTriggered = true; updateAlertState(true); } } } else { zonaAtual.innerHTML = "Falha :(&"; zonaAtual.style.color = "red"; if (alertTriggered) { alertTriggered = true; updateAlertState(true); } } lastTemperature = currentTemperature; // Update the last temperature // Print the Numeroalertas value to the HTML page var estufaRef = firebase.database().ref("Estufas/Estufa Nike/Dados"); estufaRef.once("value").then(function(snapshot) { var data = snapshot.val(); var numeroAlertas = document.getElementById("numeroalertas"); if (data && data.Numeroalertas !== undefined) { numeroAlertas.innerHTML = data.Numeroalertas; } else { numeroAlertas.innerHTML = 0; } }); } setInterval(atualizaTemperatura, 1000);
问题分析
- 页面加载时的错误触发逻辑:页面加载时直接根据数据库的
AlertaAtivado状态调用updateAlertState(true),但此时当前温度可能已经回到Normal区间,导致状态不一致,错误触发计数。 - 重复调用
updateAlertState(true):在Risco和Falha区间的else分支中,只要alertTriggered为true就重复调用updateAlertState(true),可能在页面刷新时因为状态不同步触发计数。 - 状态依赖冲突:同时依赖数据库状态和本地变量状态,未做一致性校验,导致刷新时出现逻辑矛盾。
修复后的代码
var lastTemperature; var alertTriggered = false; // 页面加载时初始化温度和告警状态 var estufaRef = firebase.database().ref("Estufas/Estufa Nike/Dados"); estufaRef.once("value").then(function(snapshot) { var data = snapshot.val(); if (data && data.UltimaTemperatura !== undefined) { lastTemperature = data.UltimaTemperatura; // 根据当前温度直接初始化告警状态,避免数据库状态滞后 alertTriggered = lastTemperature > 50; // 同步本地状态到数据库,不触发计数 syncAlertStateToDB(alertTriggered, false); } }); // 同步告警状态到数据库,addCount控制是否增加计数 function syncAlertStateToDB(alertState, addCount = true) { estufaRef.once("value").then(function(snapshot) { var data = snapshot.val(); if (!data) return; var currentDBState = data.AlertaAtivado || false; if (currentDBState !== alertState) { var updateObj = { AlertaAtivado: alertState }; // 仅当从Normal进入告警区间时才增加计数 if (alertState && addCount) { updateObj.Numeroalertas = (data.Numeroalertas || 0) + 1; } estufaRef.update(updateObj); } }); } function atualizaTemperatura() { var currentTemperature = temperaturaArray[temperaturaArray.length - 1].temperatura; document.getElementById("temperaturaatual").innerHTML = currentTemperature; var zonaAtual = document.getElementById("zonaatual"); var isInAlertZone = currentTemperature > 50; // Normal区间逻辑 if (currentTemperature <= 50) { zonaAtual.innerHTML = "Normal :)"; zonaAtual.style.color = "green"; // 从告警区间回到Normal时更新状态 if (alertTriggered) { alertTriggered = false; syncAlertStateToDB(false, false); } } // Risco区间逻辑 else if (currentTemperature > 50 && currentTemperature <= 100) { zonaAtual.innerHTML = "Risco :|&"; zonaAtual.style.color = "orange"; // 仅当从Normal进入Risco时触发计数 if (!alertTriggered && isInAlertZone) { alertTriggered = true; syncAlertStateToDB(true); } } // Falha区间逻辑 else { zonaAtual.innerHTML = "Falha :(&"; zonaAtual.style.color = "red"; // 仅当从Normal进入Falha时触发计数 if (!alertTriggered && isInAlertZone) { alertTriggered = true; syncAlertStateToDB(true); } } lastTemperature = currentTemperature; // 更新页面告警计数显示 estufaRef.once("value").then(function(snapshot) { var data = snapshot.val(); document.getElementById("numeroalertas").innerHTML = data?.Numeroalertas || 0; }); } setInterval(atualizaTemperatura, 1000);
修复说明
- 移除页面加载时的自动计数逻辑:改为根据当前温度直接初始化
alertTriggered,同步数据库时不触发计数,避免状态不一致导致的错误自增。 - 统一状态判断逻辑:用
isInAlertZone变量统一判断是否处于告警区间,减少重复代码和逻辑冲突。 - 优化状态同步函数:新增
addCount参数,仅当从Normal区间进入告警区间时才增加计数,彻底避免重复计数。 - 简化区间分支逻辑:移除Risco/Falha区间中不必要的重复状态更新,仅在状态切换时触发操作。
内容的提问来源于stack exchange,提问作者Régis Renan
相关产品推荐
相关产品推荐

