How to use socket.io in angular with node.js?

14,991

Solution 1

The one way to achieve this mechanism is using ngx-socket-io, connect your node server at the module level or root level i have implemented like below

app.module.ts code

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { SocketIoModule, SocketIoConfig } from 'ngx-socket-io';
import { AppComponent } from './app.component';
const config: SocketIoConfig = { url: 'http://192.168.1.187:9301', options: {}  };
@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    SocketIoModule.forRoot(config),
    FormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

create one service which handles your incoming and outgoing traffic.

import { Injectable } from '@angular/core';
import { Socket } from 'ngx-socket-io';
@Injectable({
  providedIn: 'root'
})
export class SocketService {

  constructor(public socket: Socket) { }
  getMessage() {
    return this.socket
        .fromEvent<any>('msg')
        .map(data => data.msg);
}

sendMessage(msg: string) {
    this.socket.emit('msg', msg);
}
}

Update your code in your component file

export class AppComponent implements OnInit {
  constructor(private socketService: SocketService) {}
  title = 'app';
  incomingmsg = [];
  msg = 'First Protocol';
  ngOnInit() {
    this.socketService
        .getMessage()
        .subscribe(msg => {
          console.log('Incoming msg', msg);
        });
        this.sendMsg(this.msg);
  }
  sendMsg(msg) {
    console.log('sdsd', msg);
    this.socketService.sendMessage(msg);
 }
}

Solution 2

Create Service and turn your socket data into Observable stream

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

@Injectable()
export class ChatService {

  observable: Observable<string>;
  socket;

  constructor() {
    this.socket = io('http://localhost:3000');     
   }

   getData(): Observable<string> {
    return this.observable = new Observable((observer) => 
      this.socket.on('hello', (data) => observer.next(data))
    );
  }

  // This one is for send data from angular to node 
  pushData(e) {
    this.socket.emit('hello', e);
  }
}

Then Call from component

App.component.ts

import { Component } from '@angular/core';
import { ChatService } from './common/chat.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {  
  title;
  chat;
  constructor(private cService: ChatService) {
    this.cService.getData().subscribe(data => console.log(data));
  }

  onClick(e: string) {
    this.cService.pushData(e);
    this.chat = '';
  }
}

Solution 3

You can create a service for working with a socket. E.g (of course this is a very simple example):

/* e.g app/shared/io/io.service.ts */

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';

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

const SERVER_URL = '/';

/** Your events enum */
export enum IOEventName {
    EVENT_NAME_1 = "EVENT_NAME_1",
    EVENT_NAME_2 = "EVENT_NAME_2",
    ...
}

/** Interfaces for your event messages */
export interface IEventName1Message {
    propOne: number,
    propTwo: string,
    ...
}

export interface IEventName2Message {
    propOne: Date,
    propTwo: Boolean,
    ...
}
...

@Injectable()
export class SocketService {
    private socket: SocketIOClient.Socket;

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

    public onEvent<T>(event: IOEventName): Observable<T | Array<T>> {
        return new Observable<T>(observer => {
            this.socket.on(event, (data: T) => observer.next(data));
        });
    }

    public destroy() {
        if (this.socket) {
            this.socket.removeAllListeners();
            this.socket.close();
            this.socket = undefined;
        }
    }
}

And use it in any components:

import { SocketService, IOEventName, IEventName1Message, IEventName2Message } 
    from 'app/shared/io/io.service';

export class AppComponent implements OnInit, OnDestroy {
    constructor(private socketService: SocketService) { }

    ngOnInit() {
        this.socketService.initSocket();
        this.socketService
            .onEvent<IEventName1Message>(IOEventName.EVENT_NAME_1)
            .subscribe(data => { /* message received */ });

        this.socketService
            .onEvent<IEventName2Message>(IOEventName.EVENT_NAME_2)
            .subscribe(data => { /* message received */ });
    }

    ngOnDestroy() {
        this.socketService.destroy();
    }
}
Share:
14,991

Related videos on Youtube

Dharmesh
Author by

Dharmesh

Reactjs, Redux, Angular, HTML, CSS, Git

Updated on June 04, 2022

Comments

  • Dharmesh
    Dharmesh almost 2 years

    Clientside I used Angular 6 and Serverside i used node.js.

    Here in angular 6 console it print message and socket.io id({message: "Hello World", id: "6An-ctwlwbZZWrfMAAAB"}) after using below code.

    this code is right or any change in this code bcoz I am not sure about this code kindly help to make correct this.

    and another query is I have more than 15 components in my project so how to make common use this socket.io for all components or I have to import this app.component.ts code in all another component.

    app.js(serverside)

    after installing (npm i socket.io)
    
    const express = require('express');
    var app = express();
    const http = require('http');
    const socketIo = require('socket.io');
    const server = http.Server(app);
    const io = socketIo(server);
    
    server.listen(3000,function(req,res){
      console.log("listen at 3000!");
    });
    
    io.on('connection',(socket) => {
      socket.emit('hello',{
        message : 'Hello World',id: socket.id
      })
    });
    

    app.component.ts(clientside)

    after installing (npm i socket.io)
    
    import * as socketIo from 'socket.io-client';
    
    export class AppComponent implements OnInit {
      ngOnInit(){
        const socket = socketIo('http://localhost:3000/');
          socket.on('hello',(data) => console.log(data));
        }
      }
    }
    
    • Chellappan வ
      Chellappan வ over 5 years
    • Chellappan வ
      Chellappan வ over 5 years
      are you getting any error?
    • Dharmesh
      Dharmesh over 5 years
      no i not getting any error console prints in crome browser like this ({message: "Hello World", id: "6An-ctwlwbZZWrfMAAAB"}) but i have more than 15 components so i dont know how to use socket.io common for all component and u told me make service for that but with service how to fetch socket.io angular to node for all components
    • Chellappan வ
      Chellappan வ over 5 years
      can you try my example code
    • Dharmesh
      Dharmesh over 5 years
      i am trying, i dont know what is this in serive import { Socket } from '../shared/interfaces';
    • Chellappan வ
      Chellappan வ over 5 years
  • Dharmesh
    Dharmesh over 5 years
    import { SocketService, IOEventName, IEventName1Message, IEventName2Message } from 'app/shared/io/io.service'; how to import this? and my node.js code is right ?
  • Lemix
    Lemix over 5 years
    @AmishaRana app/shared/io/io.service is first code block of my example. It is angular code.
  • xrobert35
    xrobert35 over 5 years
    This example is good but could be improve. Why are you returning each time a new Observable in the "onEvent" function ? Since this function can be used by many component. You should only create one by IOEventName. The initSocket is not that nice, the initSocket should be the service contructor. You should not open two socket for the same url.
  • Lemix
    Lemix over 5 years
    @xrobert35 You're right. This is a simple example, it could be improve.
  • V_for_Vj
    V_for_Vj about 4 years
    getMessage() { return this.socket .fromEvent<any>('msg') .map(data => data.msg); } this is giving me error in .map
  • V_for_Vj
    V_for_Vj about 4 years
  • pradip shinde
    pradip shinde about 4 years
    What version of angular you are using?
  • V_for_Vj
    V_for_Vj about 4 years
    i am using angular 7
  • Shofiqul Alam
    Shofiqul Alam almost 4 years
    how to add bearer token in this example? the config is in appmodule,but bearer can be available later in some other module,how to add that to each request.