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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 20:39:05