SignalR not subscribing inside Angular service

Viewed 618

I have my SignalR Angular service hooked up to the backend fine. When I log into my application, I get my access_token. I can also send messages and subscribe to the message I just sent, but I can't subscribe to it via SignalR. If I have two browsers open and I send the message via one browser. The portal signalr service message count goes up by one and the subscribe method from this line

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

returns the new message via the console.log inside that subscribe. ![enter image description here

But for some reason I can't receive the message via service.

Currently if I assign test as BehaviorSubject value:

private source = new BehaviorSubject("test");

then this line in ngOnInit inside component outputs

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

enter image description here

It never returns the newly subscribed message. Not that I would expect it to since the message isn't even coming into the service.

Although it's also worth noting I can't initialize test to it at the same time. It was more for demonstration

enter image description here

so if it's initialized as private source = new BehaviorSubject(null); component console output is Output: null

How can I get the SignalR service to return the value? It's using the azure function code from this article and it's able to connect no problem to the sample chat app in that article as well.

enter image description here

It can receive messages between 2 different browsers too via sample app so I think it's related to the client more than the backend given that this test works. I've been stuck on this for awhile so I appreciate any help!

signalr service

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();
  }

}

1 Answers

I was using code from an answer from a different post I made and I didn't realize the observable answer changed the topic name or whatever. Not sure why the EventEmitter way didn't work, but once I adjusted it to newMessage it started working.

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

to

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