aprisniak
aprisniak

Reputation: 412

Socket.io sends two messages

I'm trying to setup socket.io and here is part of my server.js

const app = require('express')();
const http = require('http').Server(app);
const io = require('socket.io')(http, { path: '/websocket', origins:'*:*' });

io.on('connection', (socket) => {
socket.send('Hi');
socket.on('message', (message) => {
    console.log(message);
    socket.emit('hello', `New: ${message}`);
});
    console.log('a user connected');
});

http.listen(3030, function(){
   console.log('listening on *:3030');
});

and my simple client:

var socket = io('https://*******.com', {
  secure: true,
  path: '/websocket'
});

const input = document.getElementById('text');
const button = document.getElementById('button');
const msg = document.getElementById('msg');

button.onclick = () => {
    socket.emit('message', input.value);
    socket.on('hello', (text) => {
        const el = document.createElement('p');
        el.innerHTML = text;
        msg.appendChild(el);
    })
}

enter image description here

And if I'll click for third time I receive a 3 messages back and so on. What I'm doing wrong? I wish to send message to the server and receive modified message back. I'm new in web sockets.

Any help appreciated.

P.S. socket.io v2.0.1

Upvotes: 2

Views: 6938

Answers (2)

Ari Waisberg
Ari Waisberg

Reputation: 1303

If you are using Angular and (probably) embedding the Socket in a Service (simpleton) you are creating a persistent listener in ngOnInit every time you load a page.

You need to create some kind of flag to know if the listener was already created in the Service from another instance of your page.

Upvotes: 0

jfriend00
jfriend00

Reputation: 708026

You are adding a socket.on() event handler each time the button is clicked. So, after the button has been clicked twice, you have duplicate socket.on() event handlers. When the event comes back, your two event handlers will each get called and you will think you are getting duplicate messages. Actually, it's just one message, but with duplicate event handlers.

You pretty much never want to add an event handler inside another event handler because that leads to this sort of build-up of duplicate event handlers. You don't describe (in words) exactly what you're code is trying to do so I don't know exactly what alternative to suggest. Usually, you set up the event handlers first, just once, when the socket is connected and then you will never get duplicate handlers.

So, perhaps it's as simple as changing this:

button.onclick = () => {
    socket.emit('message', input.value);
    socket.on('hello', (text) => {
        const el = document.createElement('p');
        el.innerHTML = text;
        msg.appendChild(el);
    })
}

to this:

button.onclick = () => {
    socket.emit('message', input.value);
}

socket.on('hello', (text) => {
    const el = document.createElement('p');
    el.innerHTML = text;
    msg.appendChild(el);
});

Upvotes: 5

Related Questions