.NET Core Razor中WebSocket onopen触发但onmessage在独立JS文件不生效
问题
我尝试通过WebSocket获取消息,代码放在.cshtml文件内时,onopen和onmessage事件均可正常触发;但将相同代码迁移至独立JavaScript文件并在页面中引入后,onopen事件能正常触发,onmessage事件却始终无法触发。
相关代码
.cshtml 文件代码
<script src="https://unpkg.com/lightweight-charts/dist/lightweight-charts.standalone.production.js"></script> <script src="~/js/klines-graph.js"></script> <script> var klines = new Klines('@Model.Symbol', '5m'); klines.createKlines(); </script>
独立JavaScript文件代码
class Klines { constructor(symbol, interval) { this.symbol = symbol; this.interval = interval; this.currentPrice = 0; this.sum = 0; this.onPriceChange = new Event('onPriceChange'); this.liveKlineSocket = new WebSocket('wss://stream.binance.com:9443/ws/' + symbol + '@@kline_5m'); const chart = LightweightCharts.createChart(document.getElementById("chart"), { width: 800, height: 400, layout: { backgroundColor: '#ffffff', textColor: 'rgba(0, 0, 0, 0.9)', }, grid: { vertLines: { color: 'rgba(0, 0, 0, 0.9)', }, horzLines: { color: 'rgba(0, 0, 0, 0.9)', }, }, crosshair: { mode: LightweightCharts.CrosshairMode.Normal, }, timeScale: { borderColor: 'rgba(0, 0, 0, 0.8)', timeVisible: true, secondsVisible: false, }, }); this.candleSeries = chart.addCandlestickSeries(); } createKlines() { fetch(`https://api.binance.com/api/v3/klines?symbol=${this.symbol}&interval=${this.interval}`) .then(response => response.json()) .then(klineData => { let candleStickList = klineData.map(item => { return { "time": item[0] / 1000, "open": item[1], "high": item[2], "low": item[3], "close": item[4] }; }); this.candleSeries.setData(candleStickList); this.currentPrice = candleStickList[candleStickList.length - 1].close; this.liveKlineSocket.addEventListener('open', function (event) { console.log('Connected to kline websocket'); }); this.liveKlineSocket.addEventListener('message', function (event) { console.log('message'); let candleStick = JSON.parse(event.data); this.candleSeries.update({ time: candleStick.openTime / 1000, open: candleStick.open, high: candleStick.high, low: candleStick.low, close: candleStick.close }); }); }).catch(er => { console.log(er); }); } }
问题原因
- this指向错误:
message事件回调使用普通function定义时,回调内部的this指向WebSocket实例而非Klines类实例,导致this.candleSeries为undefined,代码执行到this.candleSeries.update时抛出未捕获错误,后续逻辑(包括console.log('message'))完全无法执行。 - Binance数据结构解析错误:Binance返回的WebSocket k线消息嵌套在
k字段中,原代码直接访问candleStick.openTime等属性不存在,即使this指向正确也会报错。 - WebSocket地址笔误:原代码中WebSocket地址的
@@kline_5m应为@kline_5m,多一个@符号可能导致订阅主题异常(虽onopen触发,但可能影响消息接收)。
解决方案
修复this指向
有两种方式修正this指向问题:
方式1:使用箭头函数作为回调
箭头函数继承外层作用域的this(即Klines实例):
this.liveKlineSocket.addEventListener('message', (event) => { console.log('message'); let candleStick = JSON.parse(event.data); this.candleSeries.update({ time: candleStick.k.t / 1000, open: candleStick.k.o, high: candleStick.k.h, low: candleStick.k.l, close: candleStick.k.c }); });
方式2:提前保存this引用
在回调外部将this赋值给变量,回调内部使用该变量访问Klines实例:
const that = this; this.liveKlineSocket.addEventListener('message', function(event) { console.log('message'); let candleStick = JSON.parse(event.data); that.candleSeries.update({ time: candleStick.k.t / 1000, open: candleStick.k.o, high: candleStick.k.h, low: candleStick.k.l, close: candleStick.k.c }); });
修正WebSocket地址
将地址中的@@kline_5m改为@kline_5m:
this.liveKlineSocket = new WebSocket('wss://stream.binance.com:9443/ws/' + symbol + '@kline_5m');
内容的提问来源于stack exchange,提问作者Athanasios Sioppidis
相关产品推荐
相关产品推荐

