Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WebSocket in Angular 4

I am creating a chat application with Angular 4 and websocket. For this, I've followed this Angular websocket tutorial

Here is the WebsocketService source code:

import { Injectable } from '@angular/core';
import * as Rx from 'rxjs/Rx';

@Injectable()
export class WebsocketService {
  constructor() { }

  private subject: Rx.Subject<MessageEvent>;

  public connect(url): Rx.Subject<MessageEvent> {
    if (!this.subject) {
      this.subject = this.create(url);
      console.log("Successfully connected: " + url);
    } 
    return this.subject;
  }

  private create(url): Rx.Subject<MessageEvent> {
    let ws = new WebSocket(url);

    let observable = Rx.Observable.create(
    (obs: Rx.Observer<MessageEvent>) => {
        ws.onmessage = obs.next.bind(obs);
        ws.onerror = obs.error.bind(obs);
        ws.onclose = obs.complete.bind(obs);
        return ws.close.bind(ws);
    })
let observer = {
        next: (data: Object) => {
            if (ws.readyState === WebSocket.OPEN) {
                ws.send(JSON.stringify(data));
            }
        }
    }
    return Rx.Subject.create(observer, observable);
  }

}

And it is my ChatService:

import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs/Rx';
import { WebsocketService } from './websocket.service';

const CHAT_URL = 'ws://echo.websocket.org/';

export interface Message {
    author: string,
    message: string
}

@Injectable()
export class ChatService {
    public messages: Subject<Message>;

    constructor(wsService: WebsocketService) {
        this.messages = <Subject<Message>>wsService
            .connect(CHAT_URL)
            .map((response: MessageEvent): Message => {
                let data = JSON.parse(response.data);
                return {
                    author: data.author,
                    message: data.message
                }
            });
    }
}

It works fine, but I want to detect the connection status. I want to know if the connection has been interrupted or the server is down.

For that, I tried to implement an isServerOn() function inside the WebsocketService class like this:

isServerOn(): Observable<boolean> {
    return Observable.of(!!this.subject);
}

But it has not resolve the problem. Is there anyone who has encourtered the same problem?

Thank you in advance.

like image 402
Laiso Avatar asked Dec 18 '17 13:12

Laiso


People also ask

What are WebSockets in angular?

The WebSocket API is an advanced technology that allows communication between the client's browser and the server, both to send messages and to receive responses without the need to make a new request to the server to get the answer.

Is WebSocket Faster Than REST API?

Fast Reaction TimeWebSockets allow for a higher amount of efficiency compared to REST because they do not require the HTTP request/response overhead for each message sent and received.

What is difference between WebSocket and socket?

Key Differences between WebSocket and socket.ioIt provides the Connection over TCP, while Socket.io is a library to abstract the WebSocket connections. WebSocket doesn't have fallback options, while Socket.io supports fallback. WebSocket is the technology, while Socket.io is a library for WebSockets.

What is WebSocket and how it works?

The WebSocket API is an advanced technology that makes it possible to open a two-way interactive communication session between the user's browser and a server. With this API, you can send messages to a server and receive event-driven responses without having to poll the server for a reply.


1 Answers

I suggest you use type definitions for socket.io-client in your Angular application. Then define a service as follows:

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { Observer } from 'rxjs/Observer';
import { Message } from '../model/message';
import { Event } from '../model/event';

import * as socketIo from 'socket.io-client';

const SERVER_URL = 'https://yourserverhost.com';

@Injectable()
export class SocketService {
    private socket;

    public initSocket(): void {
        this.socket = socketIo(SERVER_URL);
    }

    public send(message: Message): void {
        this.socket.emit('message', message);
    }

    public onEvent(event: Event): Observable<any> {
        return new Observable<Event>(observer => {
            this.socket.on(event, () => observer.next());
        });
    }
}

Define an Event enum:

export enum Event {
    CONNECT = 'connect',
    DISCONNECT = 'disconnect'
}

Then subscribe to your service functions from your Angular component:

export class ChatComponent implements OnInit {
  constructor(private socketService: SocketService) { }

   ngOnInit(): void {
    this.initIoConnection();
  }

  private initIoConnection(): void {
    this.socketService.initSocket();

    this.ioConnection = this.socketService.onMessage()
      .subscribe((message: Message) => {
        this.messages.push(message);
      });


    this.socketService.onEvent(Event.CONNECT)
      .subscribe(() => {
        console.log('Connected to the server');
      });

    this.socketService.onEvent(Event.DISCONNECT)
      .subscribe(() => {
        console.log('Disconnected');
      });
  }
}

Find the complete chat project, which is using Node.js, WebSockets and Angular here: https://github.com/luixaviles/socket-io-typescript-chat

like image 154
luixaviles Avatar answered Sep 27 '22 21:09

luixaviles