You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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);

问题分析

  1. 页面加载时的错误触发逻辑:页面加载时直接根据数据库的AlertaAtivado状态调用updateAlertState(true),但此时当前温度可能已经回到Normal区间,导致状态不一致,错误触发计数。
  2. 重复调用updateAlertState(true):在Risco和Falha区间的else分支中,只要alertTriggered为true就重复调用updateAlertState(true),可能在页面刷新时因为状态不同步触发计数。
  3. 状态依赖冲突:同时依赖数据库状态和本地变量状态,未做一致性校验,导致刷新时出现逻辑矛盾。

修复后的代码

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);

修复说明

  1. 移除页面加载时的自动计数逻辑:改为根据当前温度直接初始化alertTriggered,同步数据库时不触发计数,避免状态不一致导致的错误自增。
  2. 统一状态判断逻辑:用isInAlertZone变量统一判断是否处于告警区间,减少重复代码和逻辑冲突。
  3. 优化状态同步函数:新增addCount参数,仅当从Normal区间进入告警区间时才增加计数,彻底避免重复计数。
  4. 简化区间分支逻辑:移除Risco/Falha区间中不必要的重复状态更新,仅在状态切换时触发操作。

内容的提问来源于stack exchange,提问作者Régis Renan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 10:53:11