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

Angular应用连接Socket时无限加载无报错,求解决方案

问题核心

你的问题根源是协议不兼容:Angular用的ngx-socket-io基于Socket.IO协议实现,而Python端的websockets库是标准WebSocket协议,两者的握手流程、消息格式完全不同,导致Angular端连接一直处于pending状态,页面卡死。


解决方案一:Python端改用Socket.IO库(推荐,适配现有Angular代码)

1. 安装依赖

pip install python-socketio python-engineio asyncio uvicorn

2. 修改Python服务端代码

import asyncio
import socketio

# 初始化Socket.IO服务,允许跨域(生产环境请指定具体域名)
sio = socketio.AsyncServer(cors_allowed_origins="*")
app = socketio.ASGIApp(sio)

# 监听连接事件
@sio.event
async def connect(sid, environ):
    print(f"客户端 {sid} 已连接")

# 监听Angular发送的message事件
@sio.event
async def message(sid, data):
    print("收到消息:", data)
    # 如需广播给所有客户端,取消下面注释:
    # await sio.emit('message', data)

# 监听断开连接事件
@sio.event
async def disconnect(sid):
    print(f"客户端 {sid} 已断开")

async def main():
    await asyncio.create_task(uvicorn.run(app, host="localhost", port=8988))

if __name__ == "__main__":
    asyncio.run(main())

3. 调整Angular的Socket服务

去掉手动调用的connect()(ngx-socket-io会自动处理连接),增加状态监听便于排查问题:

import { Injectable } from '@angular/core';
import { Socket } from 'ngx-socket-io';

@Injectable()
export class BoardSessionSocketService {
  constructor(private socket: Socket) {
    // 监听连接状态
    this.socket.on('connect', () => console.log('Socket连接成功'));
    this.socket.on('disconnect', () => console.log('Socket连接断开'));
    this.socket.on('connect_error', (err) => console.error('Socket连接失败:', err));
  }

  sendMessage(msg: string) {
    this.socket.emit('message', msg);
  }
}

解决方案二:Angular端改用原生WebSocket API(不修改Python服务)

如果不想更换Python的websockets库,直接用原生WebSocket重写Angular服务:

1. 重写Socket服务

import { Injectable } from '@angular/core';

@Injectable()
export class BoardSessionSocketService {
  private socket: WebSocket | null = null;

  constructor() {
    this.initSocket();
  }

  private initSocket() {
    this.socket = new WebSocket('ws://localhost:8988');
    
    // 连接成功回调
    this.socket.onopen = () => {
      console.log('WebSocket连接成功');
      this.sendMessage("Hello, this is angular");
    };

    // 错误回调
    this.socket.onerror = (error) => console.error('WebSocket连接错误:', error);

    // 断开连接回调,自动重连
    this.socket.onclose = () => {
      console.log('WebSocket连接关闭,3秒后尝试重连');
      setTimeout(() => this.initSocket(), 3000);
    };
  }

  sendMessage(msg: string) {
    if (this.socket && this.socket.readyState === WebSocket.OPEN) {
      this.socket.send(msg);
    } else {
      console.warn('WebSocket未连接,无法发送消息');
    }
  }
}

2. 清理Angular模块配置

删除app.module.ts中ngx-socket-io相关代码:

// 移除以下两行
// import { SocketIoModule, SocketIoConfig } from 'ngx-socket-io';
// const config: SocketIoConfig = { url: 'http://localhost:8988', options: {} };

@NgModule({
  declarations: [],
  imports: [
    // 移除 SocketIoModule.forRoot(config)
  ],
  providers: [
    BoardSessionSocketService,
    provideClientHydration()
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

3. 调整组件发送时机

避免在构造函数直接发消息(原生WebSocket连接是异步的),可以移到ngOnInit或用户触发事件:

import { Component, Input, OnInit } from '@angular/core';
import { Note } from '../board.component';
import { BoardSessionSocketService } from '../../services/board-session-socket.service';

@Component({
  selector: 'app-column',
  templateUrl: './column.component.html',
  styleUrl: './column.component.less'
})
export class ColumnComponent implements OnInit {
  @Input() columnTitle:string = ""
  @Input() notes:Note[] = []

  constructor(private boardSocket: BoardSessionSocketService) { }

  ngOnInit(): void {
    // 如需手动触发,取消下面注释(服务中已在连接成功后发送,可根据需求选择)
    // this.boardSocket.sendMessage("Hello, this is angular")
  }
}

4. Python端添加跨域支持

如果Angular运行在http://localhost:4200,修改Python服务端代码允许跨域:

async def main():
    async with websockets.serve(
        echo, 
        "localhost", 
        8988,
        extra_headers={
            "Access-Control-Allow-Origin": "http://localhost:4200",
            "Access-Control-Allow-Methods": "GET, POST, OPTIONS",
            "Access-Control-Allow-Headers": "Content-Type"
        }
    ):
        await asyncio.Future()  # 保持服务运行
asyncio.run(main())

内容的提问来源于stack exchange,提问作者Fergus O'H

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 10:10:18