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

JS中如何在条件外部获取变量值?tmp始终为0的解决方法

问题:定时器外部无法获取实时更新的tmp变量值

问题描述

我正在学习JS,通过WebSocket获取比特币USDT实时交易数据,在setInterval定时器内根据当前分钟数(51、52)记录价格并计算涨跌幅,将结果赋值给btcVariationTotal后再同步给tmp。但在定时器外部打印tmp时,它始终显示初始值0,无法获取到计算后的数值。

相关代码:

console.clear();

let wsBtc = new WebSocket('wss://stream.binance.com:9443/ws/btcusdt@trade');

let btcStockPriceElement1 = document.getElementById('btcValue1');
let btcStockPriceElement2 = document.getElementById('btcValue2');


let btcLastPrice = null;
let btcStockObject = null;

wsBtc.onmessage = (event) => {
  btcStockObject = JSON.parse(event.data);
};

let btc1 = 0, btc2 = 0;
let btcVariation_1_2 = 0;
let btcVariationTotal = 0; 

let tmp = 0; 



let btcRunTimers = setInterval(() => {
  let minutes = new Date().getMinutes();
 if (minutes === 51) {
    let val1 = parseFloat(btcStockObject.p).toFixed(1);
    let price = parseFloat(btcStockObject.p).toFixed(1);

    btcStockPriceElement1.innerText = price;
    btcStockPriceElement1.style.color =
      !btcLastPrice || btcLastPrice === price
        ? 'black'
        : price > btcLastPrice
        ? '#AAFF00'
        : 'red';

    btcLastPrice = price;
    btcStockObject = null;

    btc1 = val1;

  }

if (minutes === 52) {
    let val2 = parseFloat(btcStockObject.p).toFixed(1);
    let price = parseFloat(btcStockObject.p).toFixed(1);

    btcStockPriceElement2.innerText = price;
    btcStockPriceElement2.style.color =
      !btcLastPrice || btcLastPrice === price
        ? 'black'
        : price > btcLastPrice
        ? '#AAFF00'
        : 'red';

    btcLastPrice = price;
    btcStockObject = null;

    btc2 = val2;

    btcVariation_1_2 = ( (parseFloat(btc2) - parseFloat(btc1)) / btc1 * 100);

    document.getElementById("btcResult1").innerHTML = btcVariation_1_2.toFixed(2);
    
  }

  btcVariationTotal = (parseFloat(btcVariation_1_2));
  console.log("btc variation => " + btcVariationTotal);
  document.getElementById("result").innerHTML = btcVariationTotal.toFixed(2);
  tmp = btcVariationTotal;


}, 60000);


console.log("tmp => " +  tmp); 

原因分析

核心是JavaScript的异步执行机制:

  • setInterval属于异步任务,会被放入浏览器的事件队列中,等待所有同步任务执行完毕后才会触发。
  • 定时器外部的console.log("tmp => " + tmp)是同步任务,页面加载后会立即执行,此时定时器的回调函数还未被调用,tmp还是初始赋值的0,所以打印结果始终为0。
  • 后续定时器触发修改tmp后,如果不在触发后的时机读取,也无法获取最新值。

另外代码存在潜在风险:定时器中直接访问btcStockObject.p时,若WebSocket还未收到消息(btcStockObject为null),会抛出Cannot read property 'p' of null的错误。

解决方法

方法1:在定时器内部读取最新的tmp

把需要使用tmp的逻辑放到定时器回调内部,确保读取的是最新值:

let btcRunTimers = setInterval(() => {
  // ... 原有代码 ...

  tmp = btcVariationTotal;
  // 在这里使用最新的tmp值
  console.log("tmp(最新值) => " + tmp);
}, 60000);

方法2:用自定义事件监听tmp更新

如果需要在多个地方使用tmp的最新值,可通过自定义事件实现全局通知:

// 定义处理tmp更新的函数
function handleTmpUpdate(e) {
  console.log("tmp更新为 => " + e.detail);
}
// 监听自定义事件
document.addEventListener('tmpUpdated', handleTmpUpdate);

// 修改定时器回调
let btcRunTimers = setInterval(() => {
  // ... 原有代码 ...

  tmp = btcVariationTotal;
  // 触发自定义事件,传递最新的tmp值
  document.dispatchEvent(new CustomEvent('tmpUpdated', { detail: tmp }));
}, 60000);

方法3:修复空值报错问题

在访问btcStockObject.p前先判断对象是否存在,避免运行时错误:

if (minutes === 51) {
  if (!btcStockObject) return; // 未收到数据时直接跳过
  // ... 原有代码 ...
}

if (minutes === 52) {
  if (!btcStockObject) return; // 未收到数据时直接跳过
  // ... 原有代码 ...
}

内容的提问来源于stack exchange,提问作者elodie

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 06:50:29