Angular10+中能否在服务内注入SignalR无需在app.component调用方法
解决方案
核心思路是利用Angular的单例服务机制,将SignalR连接、监听逻辑全部封装在全局唯一的自定义服务内,自动完成初始化,无需外部手动调用启动方法。
完整服务实现代码
import { Injectable } from '@angular/core'; import { HubConnection, HubConnectionBuilder } from '@microsoft/signalr'; import { Subject } from 'rxjs'; import { environment } from 'src/environments/environment'; @Injectable({ providedIn: 'root' // 声明为全局单例服务,整个应用只会生成一个实例 }) export class ContactsSignalrService { private hubConnection: HubConnection; // 用Subject封装推送数据,对外暴露只读的可观察对象,避免外部修改数据流 private contactsSubject = new Subject<any>(); public contacts$ = this.contactsSubject.asObservable(); constructor() { // 所有初始化逻辑放在构造函数,服务实例化时自动执行,仅执行一次 this.initHubConnection(); this.registerEventListeners(); this.startConnection(); } private initHubConnection() { this.hubConnection = new HubConnectionBuilder() .withUrl(`${environment.hub}contacts`) .withAutomaticReconnect() // 内置自动重连逻辑,连接断开后自动尝试恢复 .build(); } private registerEventListeners() { this.hubConnection.on('transfercontactdata', (data) => { console.log(data, 'Hub data transfer occuring'); // 收到推送后将数据推送给所有订阅的组件 this.contactsSubject.next(data.result); }); } private startConnection() { this.hubConnection .start() .then(() => console.log('Hub Connection started')) .catch(err => console.log('Error while starting connection: ', err)); } // 可扩展封装主动调用Hub方法的公共逻辑 public invokeHubMethod(methodName: string, ...args: any[]) { return this.hubConnection.invoke(methodName, ...args); } }
使用方式
不需要在app.component.ts中手动调用初始化方法,直接在需要接收消息的组件中注入服务、订阅对应数据流即可:
// 任意业务组件示例 import { Component, OnInit } from '@angular/core'; import { ContactsSignalrService } from './contacts-signalr.service'; @Component({ selector: 'app-page-a', templateUrl: './page-a.component.html' }) export class PageAComponent implements OnInit { constructor(private contactsSignalr: ContactsSignalrService) {} ngOnInit() { // 订阅联系人推送数据 this.contactsSignalr.contacts$.subscribe(contacts => { // 此处处理业务逻辑 console.log('页面A收到更新的联系人数据:', contacts); }); } }
不管有多少个组件注入该服务,连接只会建立一次,所有订阅组件都能收到同一份推送数据。
之前问题的原因说明
- 直接注入
signalR.HubConnection报错:HubConnection是SignalR原生类,没有在Angular DI容器中注册提供器,不需要直接注入,将其封装在自定义服务内部即可。 - 服务构造函数未执行:Angular可注入服务只有被其他服务/组件注入时才会被实例化,构造函数才会执行。如果需要应用启动时立刻初始化服务,不需要等第一次注入,直接在
app.component.ts的构造函数中注入一次该服务即可,不需要调用任何方法,注入动作就会触发实例化逻辑。 - 提示缺少provider:如果服务没有设置
providedIn: 'root',也没有在对应模块的providers数组中声明,就会报缺少provider的错误,providedIn: 'root'是最简单的单例服务实现方式。
内容的提问来源于stack exchange,提问作者djangojazz
相关产品推荐
相关产品推荐

