Angular11中@microsoft/signalr注销方法后仍出现notifyresult警告如何解决
问题根源
- 重复创建Hub连接:Angular服务默认是单例模式,你在两个组件初始化时都调用
init()方法,每次调用都会创建全新的HubConnection实例,旧连接没有被正常关闭,仅移除了该实例的notifyresult监听,存活的旧连接收到服务端推送时找不到对应监听方法,直接触发警告。 - 无效的
off调用:你在init()方法中新建连接后立刻调用off('notifyresult'),此时该连接还未注册对应监听,这个调用没有任何作用。 - 连接状态无管控:没有判断当前是否已经存在可用连接,每次进入组件都会重复发起连接、注册监听流程,导致多个连接并存。
解决方案
第一步:修改signalr.service.ts,复用唯一连接,避免重复初始化
import * as signalR from '@microsoft/signalr'; import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Subject, Observable } from 'rxjs'; import { environment } from 'src/environments/environment'; interface SignalRConnectionInfo { url: string; accessToken: string; } @Injectable({ providedIn: 'root' }) export class SignalrService { orderMessages: Subject<any> = new Subject(); saleMessages: Subject<any> = new Subject(); private hubConnection?: signalR.HubConnection; private isConnecting = false; constructor(private http: HttpClient) { } private getConnectionInfo(): Observable<SignalRConnectionInfo> { return this.http.get<SignalRConnectionInfo>(environment.signalRUrl); } init() { // 已有连接或正在连接中,直接返回避免重复创建 if (this.hubConnection || this.isConnecting) return; this.isConnecting = true; this.getConnectionInfo().subscribe(info => { const options = { accessTokenFactory: () => info.accessToken }; this.hubConnection = new signalR.HubConnectionBuilder() .withUrl(info.url, options) .withAutomaticReconnect([0, 1000, 5000, null]) .configureLogging(signalR.LogLevel.Information) .build(); // 注册全局唯一的notifyresult监听,不需要重复注册/移除 this.hubConnection.on('notifyresult', (data: any) => { if(data == "Orders") { this.orderMessages.next(data); } else { this.saleMessages.next(data); } }); this.hubConnection.start() .then(() => this.isConnecting = false) .catch(err => { console.error(err.toString()); this.isConnecting = false; }); }); } // 提供统一的连接销毁方法,可在项目退出登录等场景调用 destroyConnection() { if (this.hubConnection) { this.hubConnection.stop().catch(err => console.error(err)); this.hubConnection = undefined; this.isConnecting = false; } } }
第二步:简化组件逻辑,不需要操作hub连接的监听注销
orders.component.ts修改后代码:
public orderMessageSubscription: any; ngOnInit(): void { this.signalRService.init(); this.orderMessageSubscription = this.signalRService.orderMessages.subscribe(message => { // 你的业务逻辑 }); } ngOnDestroy() { // 只需要取消当前组件的Subject订阅即可,不需要操作hub连接的off方法 this.orderMessageSubscription?.unsubscribe(); }
sales.component.ts修改后代码:
public saleMessageSubscription: any; ngOnInit(): void { this.signalRService.init(); this.saleMessageSubscription= this.signalRService.saleMessages.subscribe(message => { // 你的业务逻辑 }); } ngOnDestroy() { this.saleMessageSubscription?.unsubscribe(); }
修改后整个应用只会创建一个Hub连接,所有组件共用同一个连接,不会出现旧连接残留的问题;notifyresult监听只会注册一次,不会被重复移除,服务端推送消息永远有对应处理方法,不会触发警告;组件销毁时只需要取消自己的Subject订阅,不会影响全局的Hub连接逻辑,下次进入组件直接订阅就能收到消息,不需要重新初始化连接。
内容的提问来源于stack exchange,提问作者RGS
相关产品推荐
相关产品推荐

