Angular 16中Unsubscribe is not a function错误的原因及解决方法
错误原因与修正方案
错误原因
你遇到的TypeError: this.getMsgSubscription.unsubscribe is not a function错误,核心问题是:
- 你的
getMsg方法声明返回RxJS Subscription,但实际返回的是socket.io的on()方法的结果——这个结果是一个移除监听的普通函数,并非Angular RxJS标准的Subscription对象。 - 当你把这个普通函数赋值给
getMsgSubscription后,调用unsubscribe()自然会报错,因为该函数没有这个方法。
修正步骤
1. 重构Service代码:将Socket事件包装为RxJS Observable
把socket.io的事件监听逻辑包装成RxJS Observable,这样订阅后就能得到标准的Subscription对象,同时正确实现取消监听的逻辑:
import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class Sockservice { // 假设this.socket是已初始化的socket.io客户端实例 getMsg(users_data: any): Observable<any> { return new Observable(observer => { // 定义socket事件的处理函数 const messageHandler = async (data: any) => { if (users_data.user1._id === data.sender_id && users_data.user2._id === data.reciever_id) { const container = document.getElementById('chat-container'); const element = document.createElement('ul'); if (this.msg !== data.message) { element.innerHTML = data.message; element.style.textAlign = 'right'; container?.appendChild(element); } } }; // 注册socket事件监听 this.socket.on('loadNewChat', messageHandler); // 返回取消订阅的清理逻辑:移除socket事件监听 return () => { this.socket.off('loadNewChat', messageHandler); }; }); } }
2. 调整Component代码:正确订阅Observable
在组件中订阅Observable,得到标准的Subscription对象,在组件销毁时调用unsubscribe():
import { Component, OnInit, OnDestroy, Inject } from '@angular/core'; import { Subscription } from 'rxjs'; import { Sockservice } from './path-to-your-service'; // 假设你用的是MatDialog,引入对应的依赖 import { MAT_DIALOG_DATA } from '@angular/material/dialog'; @Component({ selector: 'app-your-component', templateUrl: './your-component.component.html', styleUrls: ['./your-component.component.css'] }) export class YourComponent implements OnInit, OnDestroy { private getMsgSubscription?: Subscription; dialogdata: any; UserData: any = { sender_id: '', reciever_id: '' }; constructor( private sockservice: Sockservice, @Inject(MAT_DIALOG_DATA) public data: any ) {} ngOnInit(): void { this.dialogdata = this.data; this.UserData.sender_id = this.dialogdata.user2._id; this.UserData.reciever_id = this.dialogdata.user1._id; // 订阅Observable,获得标准Subscription this.getMsgSubscription = this.sockservice.getMsg(this.dialogdata).subscribe(); this.sockservice.getChats(this.UserData); } ngOnDestroy(): void { // 安全调用unsubscribe,避免空值报错 this.getMsgSubscription?.unsubscribe(); } }
额外优化建议
- 避免直接操作DOM:Angular推荐通过数据绑定渲染视图。可以将消息存入组件数组,用
*ngFor动态渲染,而非直接appendChild。 - 类型安全:不要用
any类型,定义User、ChatMessage等接口,提升代码可维护性。
内容的提问来源于stack exchange,提问作者themadhatter
相关产品推荐
相关产品推荐

