5

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

}

7
  • Can you post your component code? It sounds like you may be getting a different instance of the service when you are injecting it. Commented Jul 7, 2020 at 18:06
  • I don't think it's the component that is the issue. If I put a console.log(data) right above the this.source.next(data) inside signalr service method private registerSignalEvents() then it never outputs. If I open a different browser and place a bid in the first browser with the console.log in the service then I never see that in the second browser. Commented Jul 7, 2020 at 18:21
  • Reading it over again, I don't think there is an issue with it either. I thought you may be providing a separate instance of the service, but if you were you would probably be getting double the values since each service would be listening to and responding to the events. Commented Jul 7, 2020 at 18:29
  • Correct. Can't retrieve the new message any other way at this time except from http.post subscribe for some reason. So only the same instance that sent the message can see the message technically Commented Jul 7, 2020 at 18:36
  • Did you try using EventEmitter? Commented Jul 10, 2020 at 13:42

1 Answer 1

3

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)
    });
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.