【问题标题】:SignalR not subscribing inside Angular serviceSignalR 未在 Angular 服务中订阅
【发布时间】:2020-10-26 15:10:57
【问题描述】:

我的 SignalR Angular 服务很好地连接到后端。当我登录到我的应用程序时,我得到了我的 access_token。我也可以发送消息并订阅我刚刚发送的消息,但我无法通过 SignalR 订阅它。如果我打开了两个浏览器并通过一个浏览器发送消息。门户信号器服务消息计数增加 1 并且此行的 subscribe 方法

 this.http.post('http://localhost:7070/api/messages', message).pipe(takeUntil(this.destroy)).subscribe(data => console.log(data));

通过订阅中的 console.log 返回新消息。

但由于某种原因,我无法通过服务接收消息。

目前,如果我将 test 分配为 BehaviorSubject 值:

private source = new BehaviorSubject("test");

然后组件内的 ngOnInit 中的这一行输出

this.signalRService.signalReceived.subscribe(data => console.log("Output:", data))

它永远不会返回新订阅的消息。不是我期望它,因为消息甚至没有进入服务。

虽然也值得注意我不能同时初始化测试。更多是为了演示

所以如果它被初始化为private source = new BehaviorSubject(null); 组件控制台输出为Output: null

如何让 SignalR 服务返回值?它使用来自this article 的天蓝色函数代码,并且它也能够毫无问题地连接到该文章中的示例聊天应用程序。

它也可以通过示例应用程序在 2 个不同的浏览器之间接收消息,因此鉴于此测试有效,我认为它与客户端的关系多于后端。我已经坚持了一段时间,所以我很感激任何帮助!

信号服务

import { Injectable, EventEmitter, OnDestroy, Output } from "@angular/core";
import * as signalR from "@microsoft/signalr";
import { SignalViewModel } from "./signal-view-model";
import { HttpClient, HttpParams } from "@angular/common/http";
import { BehaviorSubject, Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

@Injectable({
  providedIn: "root"
})

export class SignalRService implements OnDestroy {
  @Output() onSignalRMessage: EventEmitter<any> = new EventEmitter();
  private hubConnection: signalR.HubConnection;
  private source = new BehaviorSubject(null);
  signalReceived = this.source.asObservable();
  destroy = new Subject();
  constructor(private http: HttpClient) {
    this.buildConnection();
    this.startConnection();
  }

  private buildConnection = () => {
    this.hubConnection = new signalR.HubConnectionBuilder()
      .withUrl("http://localhost:7070/api")
      .build();
  }

  sendMessage(message: SignalViewModel) {
    this.http.post('http://localhost:7070/api/messages', message).pipe(takeUntil(this.destroy)).subscribe(data => console.log(data));
  }

  private startConnection = () => {
    this.hubConnection
      .start()
      .then(() => {
        console.log("Connection Started...");
        this.registerSignalEvents();
      })
      .catch(err => {
        console.log("Error while starting connection: " + err);

        //if you get error try to start connection again after 3 seconds.
        setTimeout(function () {
          this.startConnection();
        }, 3000);
      });
  }

  private registerSignalEvents() {
    this.hubConnection.on("SignalMessageReceived", (data: SignalViewModel) => {
      this.source.next(data)
    });
  }

  private newMessage(data: SignalViewModel) {
    this.onSignalRMessage.emit(data);
  }


  getSignalReceived() {
    return this.signalReceived;
  }

  ngOnDestroy() {
    this.destroy.next();
    this.destroy.complete();
  }

}

【问题讨论】:

  • 你能发布你的组件代码吗?听起来您在注入服务时可能会获得不同的服务实例。
  • 我认为问题不在于组件。如果我将console.log(data) 放在this.source.next(data) 内部信号服务方法private registerSignalEvents() 的正上方,那么它永远不会输出。如果我打开不同的浏览器并在第一个浏览器中使用 console.log 在服务中出价,那么我永远不会在第二个浏览器中看到它。
  • 再读一遍,我觉得也没有问题。我认为您可能会提供服务的单独实例,但如果您提供了服务,您可能会获得双倍的价值,因为每个服务都会监听和响应事件。
  • 正确。由于某种原因,除了从 http.post subscribe 之外,目前无法以任何其他方式检索新消息。所以只有发送消息的同一个实例才能在技术上看到消息
  • 您是否尝试过使用EventEmitter?

标签: angular signalr azure-functions


【解决方案1】:

我正在使用来自我发布的另一篇帖子的answer 中的代码,但我没有意识到可观察到的答案改变了主题名称或其他任何内容。不知道为什么 EventEmitter 方式不起作用,但是一旦我将它调整为 newMessage 它就开始工作了。

 private registerSignalEvents() {
    this.hubConnection.on("SignalMessageReceived", (data: SignalViewModel) => {
      this.source.next(data)
    });

到

  private registerSignalEvents() {
    this.hubConnection.on("NewMessage", (data: SignalViewModel) => {
      this.source.next(data)
    });

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-23
    • 1970-01-01
    • 2018-05-07
    相关资源
    最近更新 更多