jmlemetayer
jmlemetayer

Reputation: 4952

Filter web socket messages into multiple Observables

In my angular application, I am using web sockets to receive asynchronous messages from my back-end. So I have created an angular service to handle this:

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import * as SocketIO from 'socket.io-client';

@Injectable({
    providedIn: 'root'
})

export class EventService {
    private socket;

    constructor() {
        this.socket = SocketIO();
    }

    onMessage(): Observable<any> {
        return new Observable<any>(observer => {
            this.socket.on('message', (message: string) => {
                observer.next(JSON.parse(message))
            });
        });
    }
}

My messages have different types and are JSON formatted this way:

{
    "type": "HELLO",
    "data": "hello world !"
}

Currently, I use the EventService.onMessage().subscribe(...) function to handle messages in the only component which need them.


Now, I need to have multiple message types. Which will be used by multiple components.

I would like to create a method which return an Observable by message types. Something like that:

export class EventService {
    ...

    onHello(): Observable<any> { ... }

    onFoo(): Observable<any> { ... }

    onBar(): Observable<any> { ... }
}

Is it possible ? How to do it ? Is the back-end architecture correct (maybe I should split into multiple web sockets) ?

Upvotes: 0

Views: 1509

Answers (2)

jmlemetayer
jmlemetayer

Reputation: 4952

I fact, as I am using socket.io there a simple solution.

I was sending data in my back-end using the send() function:

const io = require('socket.io');
const ws = io(...);

ws.on('connection', function(socket) {
    ...

    socket.send(JSON.stringify({
        type: "HELLO",
        data: "hello world !"
    }));
});

Which send a 'message' which can be receive using on('message', ...).

But I should use the emit() function instead which allow to set the event name:

const io = require('socket.io');
const ws = io(...);

ws.on('connection', function(socket) {
    ...

    socket.emit('hello', JSON.stringify({
        data: "hello world !"
    }));
});

So now my angular service could be:

export class EventService {
   ...

    onHello(): Observable<any> {
        return new Observable<any>(observer => {
            this.socket.on('hello', (message: string) => {
                observer.next(JSON.parse(message))
            });
        });
    }
}

Upvotes: 0

Damian Pioś
Damian Pioś

Reputation: 483

maybe try in different way: create subjects for each message type, and in onMessage method apply message to specyfic subject

onHello() = new Subject()/new BehaviorSubject(initialValue)
...

onMessage() {
  this.socket.on('message', message => {
    let msg = JSON.parse(message);
    if(msg.type === 'hello'){
      this.onHello.next(msg);
    }
    ...
  }
}

Upvotes: 1

Related Questions