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
相关产品推荐
相关产品推荐

