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

Angular结合WebSocket与Data Table时出现Cannot read property 'on' of undefined错误

解决Angular中WebSocket结合Data Table DataSource时的"Cannot read property 'on' of undefined"错误

你遇到的问题根源在于socket的初始化时机和类上下文的错误使用,我来帮你一步步修正:

错误原因分析

你原来的代码里把this.socket.on("add", ()=>{ this.connect() })写在了UserDataSource类的外部,这时候this根本不指向类的实例,而且socket也没有在正确的上下文里初始化,自然会抛出undefined的错误。另外,原有的connect方法只是直接返回服务的Observable,就算调用它也没法让Data Table感知到数据更新。

修正后的完整代码

首先调整UserDataSource的实现,用BehaviorSubject来维护可更新的数据流,并在类的构造函数里正确初始化socket和监听事件:

import * as io from "socket.io-client";
import { DataSource } from '@angular/cdk/collections';
import { Observable, BehaviorSubject } from 'rxjs';
import { NouveauProjet } from './your-model-path'; // 替换成你实际的模型文件路径
import { AjoutprojService } from './your-service-path'; // 替换成你实际的服务文件路径

export class UserDataSource extends DataSource<NouveauProjet> {
  private socket: SocketIOClient.Socket;
  // 用BehaviorSubject来保存当前数据,支持订阅和更新通知
  private dataSubject = new BehaviorSubject<NouveauProjet[]>([]);

  constructor(private ajoutProj: AjoutprojService) {
    super();
    // 在构造函数中初始化socket,确保类实例创建时socket已就绪
    this.socket = io('http://127.0.0.1:8080');
    // 初始化socket事件监听
    this.setupSocketListeners();
    // 加载初始数据
    this.refreshData();
  }

  // 封装数据加载逻辑,方便重复调用
  private refreshData(): void {
    this.ajoutProj.getAllProj().subscribe(projets => {
      this.dataSubject.next(projets);
    });
  }

  // 封装socket事件监听
  private setupSocketListeners(): void {
    this.socket.on("add", () => {
      // 收到add事件时,重新加载数据并通知Data Table更新
      this.refreshData();
    });
  }

  connect(): Observable<NouveauProjet[]> {
    // 返回BehaviorSubject的Observable,让Data Table订阅数据变化
    return this.dataSubject.asObservable();
  }

  disconnect(): void {
    // 组件销毁时清理资源,避免内存泄漏
    this.dataSubject.complete();
    this.socket.disconnect();
  }
}

然后调整你的组件代码,正确使用这个DataSource:

import { Component, OnInit, OnDestroy } from '@angular/core';
import { AjoutprojService } from './your-service-path';
import { UserDataSource } from './your-datasource-path';

@Component({
  selector: "app-liste-projets",
  templateUrl: "./liste-projets.component.html",
  styleUrls: ["./liste-projets.component.css"]
})
export class ListeProjetsComponent implements OnInit, OnDestroy {
  dataSource: UserDataSource;

  constructor(private ajoutProj: AjoutprojService) {}

  ngOnInit(): void {
    // 初始化DataSource
    this.dataSource = new UserDataSource(this.ajoutProj);
  }

  ngOnDestroy(): void {
    // 组件销毁时关闭socket连接,清理资源
    this.dataSource.disconnect();
  }
}

关键修正点

  1. socket初始化移到构造函数:确保socket在类实例创建时就被正确初始化,避免undefined问题。
  2. 用BehaviorSubject管理数据流:这样当WebSocket触发add事件时,我们可以通过next方法把新数据推送给订阅者(也就是你的Data Table),实现自动更新。
  3. 事件监听放在类内部:确保this指向类实例,能正确访问socket和类的方法。
  4. 添加资源清理逻辑:在组件销毁时断开socket连接并完成Subject,防止内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:49:01