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(); } }
关键修正点
- socket初始化移到构造函数:确保socket在类实例创建时就被正确初始化,避免undefined问题。
- 用BehaviorSubject管理数据流:这样当WebSocket触发
add事件时,我们可以通过next方法把新数据推送给订阅者(也就是你的Data Table),实现自动更新。 - 事件监听放在类内部:确保
this指向类实例,能正确访问socket和类的方法。 - 添加资源清理逻辑:在组件销毁时断开socket连接并完成Subject,防止内存泄漏。
内容的提问来源于stack exchange,提问作者Hamza Haddad
相关产品推荐
相关产品推荐

