两个WebSocket连接冲突:切换BTC/ETH实时价格时反复跳转如何解决?
问题根因
你当前的代码存在两个核心问题:
- 页面加载时就同时建立了比特币、以太坊两个WebSocket连接,两个连接全程都在持续接收服务端推送的价格数据
- 点击对应币种按钮仅会给对应WebSocket绑定
onmessage回调,之前绑定的回调不会被自动移除,因此点击过两个按钮后,两个回调都会触发、同时给同一个DOM元素赋值,自然会出现价格来回跳动的问题
直接关闭连接会导致后续无法重新获取对应币种的价格,完全没必要采用这种处理方式。
修复方案
最优方案(单连接实现)
只需要建立一个WebSocket连接同时订阅两个币种,通过标记变量控制要展示的价格即可,既省资源逻辑也更简单:
// 初始化时同时订阅两个币种的价格推送 const pricesWs = new WebSocket('wss://ws.coincap.io/prices?assets=bitcoin,ethereum') // 标记当前需要展示的币种,可根据需求设置默认值 let currentShowAsset = 'bitcoin' $(document).ready(function() { // 全局只绑定一次消息回调,根据当前标记更新对应价格 pricesWs.onmessage = function (msg) { const priceData = JSON.parse(msg.data) if(priceData[currentShowAsset]) { document.getElementById("btc").innerHTML = parseFloat(priceData[currentShowAsset]) } } // 比特币按钮点击仅修改展示标记 $('.buttonbtc').click(function(e) { currentShowAsset = 'bitcoin' }) // 以太坊按钮点击仅修改展示标记 $('.buttoneth').click(function(e) { currentShowAsset = 'ethereum' }) })
兼容原有双连接逻辑的修复方案
如果要保留你原有双连接的写法,只需要每次点击按钮时把另一个WebSocket的消息回调置空即可,不需要关闭连接:
const pricesWs = new WebSocket('wss://ws.coincap.io/prices?assets=bitcoin') const pricesWs1 = new WebSocket('wss://ws.coincap.io/prices?assets=ethereum') $(document).ready(function() { $('.buttonbtc').click(function(e) { // 清空以太坊连接的消息回调 pricesWs1.onmessage = null pricesWs.onmessage = function (msg) { var str = msg.data var matches = str.match (/\b\d+(?:.\d+)?/); var finalprice = parseFloat(matches); document.getElementById("btc").innerHTML = finalprice; } }) $('.buttoneth').click(function(e) { // 清空比特币连接的消息回调 pricesWs.onmessage = null pricesWs1.onmessage = function (msgg) { var str = msgg.data var matches = str.match (/\b\d+(?:.\d+)?/); var finalprice = parseFloat(matches); document.getElementById("btc").innerHTML = finalprice; } }) })
优化提示
- 优先选择单连接方案,coincap接口返回的是标准JSON格式,直接用
JSON.parse解析即可拿到对应币种的价格,不需要正则匹配,稳定性更高 - 可以补充WebSocket异常断开的重连逻辑,避免连接意外断开后无法更新价格
内容的提问来源于stack exchange,提问作者in2d
相关产品推荐
相关产品推荐

