Chat in SocketIO with Angular and NodeJS it is working only in localhost as realtime but not in different pc

  angular, javascript, node.js, socket.io, typescript

I have implemented a realtime chat in Angular with SocketIO.
The chat it is working in realtime but only in one machine or PC.
If I try to login in another pc with another user and I try to send chat it needs to be reloaded the component to see new messages.

The server.js or backend it starts in both devices, maybe there is the problem, but I am not sure.

The socketIO it is so configured that it will not take a default PORT.

This is my code in Backend.

const socketIO = require('socket.io');
const app = express();

const server = http.Server(app);

const io = socketIO(server, {
  cors: {
  origin: "*",
  credentials: true
  }
});
app.set('io', io);

const PORT = 5000;

server.listen(PORT);

This is the model in backend.

const mongoose = require("mongoose");
const Schema = mongoose.Schema;

const schema = new Schema({
    emitterId: {type: String, required: true},
    emitter: {type:String, required: true},
    content: {
        type : { type : String },
        value: { type : String },
    },
    timestamp: { type : Date, default: Date.now }
});

schema.set("toJSON", {virtuals: true});
module.exports = mongoose.model("Message", schema);

This is routes in backend

const MessagesController = require("../controllers/messageController");

const routes = express.Router();

/** Messages */
routes.post("/createMessage", MessagesController.createNewMessage);
routes.get("/messages", MessagesController.findAllMessages);
routes.post("/getMessages", MessagesController.getMessages);

This is the service.

const Message = require("../models/message");

async function createMessage(payload) {
    const newMessage = new Message(payload);
    await newMessage.save();
}
async function findMessages() {
    return await Message.find();
}

async function getMessages({userId, toUserId}) {
    const data = {
        '$or' : [
            { '$and': [
                    {
                        'emitter': userId
                    },
                    {
                        'emitterId': toUserId
                    }
                ]
            },
            {
                '$and': [
                    {
                        'emitter': toUserId
                    }, {
                        'emitterId': userId
                    }
                ]
            },
        ]
    };
    return await Message.find(data);
}

module.exports = {
    createMessage,
    findMessages,
    getMessages
}

And this is my Controller.

const messageService = require("../service/message.service");


function createNewMessage(req, res, next) {
    const io = req.app.get("io");
    messageService.createMessage(req.body)
        .then(() => {
            res.status(200).json();
            io.emit("newMessage", req.body);
        })
        .catch(err => next(err));
}
function getMessages(req, res, next) {
    let userId = req.body.emitterId;
    let toUserId = req.body.emitter;
         messageService.getMessages({
            userId: userId,
            toUserId: toUserId
        }).then(msg => res.json(msg))
             .catch(err => next(err));
}
module.exports = {
    createNewMessage,
    findAllMessages,
    getMessages
}

And this is the part on the Frontend

  <div class="chat-message">
    <div class="message-list">
        <ul #messageThread class="message-thread" *ngIf="messages.length !== 0">
          <li *ngFor="let message of messages; trackBy: trackThings" [class.align-left]="!alignMessage(message.emitterId)" [class.align-right]="alignMessage(message.emitterId)" [tooltip]="message.timestamp | date: 'MMM d, y, h:mm:ss a'">
            {{ message.content.value}}
          </li>
        </ul>

    </div>


 constructor(
    public msgHelperService: MessageHelperService,
    public authService: AuthService,
    public cd: ChangeDetectorRef) {
    this.socket = io(environment.backend);

  }

  ngOnInit(): void {
      this.getMessages();
      this.cd.detectChanges();
      this.scrollMessageContainer();
      this.socket.on("newMessage", (payload) => {
      this.getMessages();
    })
  }
 sendMessage(friend) {
    const msgObj = {
      emitterId: friend.uniqueId,
      emitter: this.authService.userID,
      content: {
        value: this.message
      },
      timestamp: new Date(),
    }
    this.msgHelperService.createMessage(msgObj).pipe().subscribe();
    this.message = "";
    this.scrollMessageContainer();
    setTimeout(()=>{
      this.socket.on("newMessage", () =>{
        this.getMessages();
      });
    }, 500);
    this.cd.detectChanges();
  }



getMessages() {
    this.socket.on("newMessage", () => {
      this.msgHelperService.getMessages(this.authService.userID, this.selectedUser).subscribe((response: Messages[]) => {
        this.messages = response;
        this.scrollMessageContainer();
      });
    })
    this.msgHelperService.getMessages(this.authService.userID, this.selectedUser).subscribe((response: Messages[]) => {
      this.messages = response;
      this.scrollMessageContainer();
    })
  }

  alignMessage(userId: string): boolean {
    return this.authService.userID !== userId;
  }

This is the helper service.

@Injectable({
  providedIn: "root"
})

export class MessageHelperService {

  constructor(private messageService: MessagesService) {
  }

  createMessage(message): Observable<Messages> {
    return new Observable(observer => {
      this.messageService.createRequest(message).subscribe(() => {
        observer.next();
      })
    })
  }

  getMessages(toUserId, authId): Observable<any> {
      return new Observable<any>(observer => {
        this.messageService.getMessages({emitter: authId, emitterId: toUserId}).subscribe(result => {
          observer.next(result);
        })
      })
  }
  getYourMessages(authId): Observable<any> {
    return new Observable<any>(observer => {
      this.messageService.getYourMessages({emitter: authId}).subscribe(result => {
        observer.next(result);
      })
    })
  }
}

And this is the service for Http.

@Injectable({
  providedIn: "root"
})
export class MessagesService {
  public baseUrl = environment.backend;
  private httpOptions = {
    headers: new HttpHeaders({
      "Content-Type": "application/json",
    })
  };
  constructor(private http: HttpClient) { }

  createRequest(newRequest: Messages) {
    return this.http.post<Messages>(`${this.baseUrl}/createMessage`, newRequest)
      .pipe(map(res => {
        return res;
      }))
  }

  getAllMsg() {
    return this.http.get<any[]>(`${this.baseUrl}/messages`);
  }

  getMessages(params: Messages): Observable<MessagesResponse> {
    return this.http.post(`${this.baseUrl}/getMessages`, JSON.stringify(params), this.httpOptions).pipe(
      map((response: MessagesResponse) => {
        return response;
      },
        (err) => {
        throw err;
        })
    )
  }
  getYourMessages(params: Messages): Observable<MessagesResponse> {
    return this.http.post(`${this.baseUrl}/getYourMessages`, JSON.stringify(params), this.httpOptions).pipe(
      map((response: MessagesResponse) => {
          return response;
        },
        (err) => {
          throw err;
        })
    )
  }
}

The environment looks like this.

export const environment = {
  production: false,
  backend: "http://localhost:5000"
};

Source: Angular Questions

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.