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

Django+Vue+WebSocket客户端实现问题:数据不展示、仅接收一次如何解决

问题1:数据存入变量但表格不渲染的原因及修复

原因有两点:

  • WebSocket 接收到的event.data是JSON字符串格式,你没有将其转为JavaScript对象,直接赋值给数组类型的signals后,v-for无法正常遍历字符串渲染表格。
  • 后端当前返回的是单条对象数据,而signals定义为数组类型,直接赋值会覆盖数组结构,导致遍历逻辑失效。

修复Vue侧代码,修改getSignals方法里的onmessage回调即可:

this.connection.onmessage = (event) => {
  // 先把JSON字符串转成JS对象
  const newSignal = JSON.parse(event.data)
  console.log("Successfully retrieved message from websocket", newSignal)
  // 如果是单条数据需要追加到列表里,用push
  this.signals.push(newSignal)
  // 如果是要全量替换列表数据,就赋值为数组格式:this.signals = [newSignal]
}

问题2:只能接收一次数据的原因及修复

原因有两点:

  1. 当前Django的WSConsumer只在连接建立的connect方法里执行了一次send,后续没有新数据推送的逻辑,自然只能收到一次。
  2. 前端没有配置WebSocket的异常、断开重连逻辑,连接意外断开后无法自动恢复接收数据。

前端修复:

监听器放在created钩子是合理的,补充异常、断开重连逻辑,同时加组件销毁时关闭连接的逻辑,避免内存泄漏:

export default {
    name: 'Signals',
    data() {
        return {
            signals: [],
            connection: null,
            reconnectTimer: null
        }
    },
    created() {
        this.initWebSocket()
    },
    beforeDestroy() {
        // 组件销毁时关闭连接,清除重连定时器
        this.connection.close()
        if (this.reconnectTimer) clearTimeout(this.reconnectTimer)
    },
    methods: {
        initWebSocket() {
            console.log("Starting connection to websocket")
            this.connection = new WebSocket('ws://localhost:8000/ws/signals/')
            this.connection.onmessage = (event) => {
                const newSignal = JSON.parse(event.data)
                this.signals.push(newSignal)
            }
            this.connection.onerror = (err) => {
                console.error("WebSocket error: ", err)
            }
            this.connection.onclose = () => {
                console.log("WebSocket disconnected, try to reconnect after 3s")
                // 断开后3s自动重连
                this.reconnectTimer = setTimeout(() => {
                    this.initWebSocket()
                }, 3000)
            }
        }
    }
}

后端修复:

如果需要后续主动推送新数据,不能只在connect里发一次,建议用Channels的分组推送功能,示例代码:

import json
from channels.generic.websocket import WebsocketConsumer
from asgiref.sync import async_to_sync

class WSConsumer(WebsocketConsumer):
    def connect(self):
        self.accept()
        # 把当前连接加入signals_group分组
        async_to_sync(self.channel_layer.group_add)(
            "signals_group",
            self.channel_name
        )
        # 连接建立时的首次推送
        self.send(json.dumps({
            'id': 1,
            'date': "date",
            'marketOpen': "marketOpen",
            'symbol': "symbol",
            'trade': "trade",
            'bias': "bias",
            'status': "status"
            }))
    
    # 处理分组推送的消息
    def send_signal(self, event):
        data = event['data']
        self.send(json.dumps(data))
    
    def disconnect(self, close_code):
        # 断开连接时移出分组
        async_to_sync(self.channel_layer.group_discard)(
            "signals_group",
            self.channel_name
        )

后续需要推送新数据的地方,调用如下代码即可给所有连接的前端推送:

from channels.layers import get_channel_layer
from asgiref.sync import async_to_sync

channel_layer = get_channel_layer()
async_to_sync(channel_layer.group_send)(
    "signals_group",
    {
        "type": "send.signal",
        "data": {
            # 新的信号数据
            'id': 2,
            'date': "2024-01-01",
            'marketOpen': "是",
            'symbol': "BTC",
            'trade': "做多",
            'bias': "多",
            'status': "生效中"
        }
    }
)

额外说明

控制台里的Unchecked runtime.lastError报错是浏览器插件导致的,和你的业务代码无关,可以忽略。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 03:45:03