7

The problem is that Whenever I try to fire "this.io.emit" event a TypeError occurs. It gives only while I write this statement "this.io.emit" inside "socket.on" block otherwise, if I write it outside this block it generates no error.

This is the main server.js file to call the other libraries:

const express = require('express'),
http = require('http'),
socketio = require('socket.io');

class App{

constructor()
{
    this.port =  process.env.PORT || 81;
    this.host = `localhost`;        
    this.app = express();
    this.http = http.Server(this.app);
    this.socket = socketio(this.http);
}
appConfig(){
    new config(this.app);
}
appRoutes(){
    new routes(this.app,this.socket).routesDefault();
}
appDefault(){
    this.appConfig();
    this.appRoutes();
    this.http.listen(this.port,this.host,()=> {
        console.log(`Listening`);
    });
}}

my server side code is:

'use strict';
class Routes {

constructor(app,socket) {
    this.app = app;
    this.io = socket;
    this.users=[];
}

routesTemplate()
{
    this.app.get('/',function(req,res){
        res.render('index');
    });
}

socketEvents()
{
    this.io.on('connection',(socket) => {
        socket.on('send message',function(data)
        {
            this.io.emit('new message',data);//here the error lies.
        });
    }); 
}
routesDefault()
{
    this.routesTemplate();
    this.socketEvents();
}}  
module.exports = Routes;

I also tried to access "this.users.The length" inside socket.on the statement and it generated the same TypeError: cannot read property length. I have no idea why it is occurring. Please help me to resolve this problem.

Client Side:

        <script>
        $(function($){
            var socket = io.connect();
            var $messageForm = $('#send-message');
            var $messageBox = $('#message');
            var $chat = $('#chat');

            $messageForm.submit(function(e){
                e.preventDefault();
                socket.emit('send message',$messageBox.val());
                $messageBox.val("");
            });
            socket.on('new message',function(data){
                $chat.append(data+ "<br/>");
            });
        });
    </script>
sagar
  • 732
  • 1
  • 6
  • 25

3 Answers3

7

The context of this is an issue in your code. To pass the current context use bind or the Arrow Function. In javascript, the value of this is defined by how you called the function, which in your case is socket object.

socketEvents()
{
    this.io.on('connection',(socket) => {
        socket.on('send message',function(data)
        {
            this.io.emit('new message',data);//here the error lies.
        }bind(this));
    }); 
}

P.S.: Edited, now this code works fine. I would like to suggest the below post described about it.

What are the differences (if any) between ES6 arrow functions and functions bound with Function.prototype.bind?

Community
  • 1
  • 1
Abhinav Galodha
  • 9,293
  • 2
  • 31
  • 41
  • But i have another application exactly similiar ,the difference is There I am using angularJS which gives no error if use the errorneous syntax "this.io.emit" . Which blow up my mind that. Is there any difference in treating "this" in both (javascript and angularJS) ? – sagar Feb 02 '17 at 19:48
  • Can you show that code? It depends on how the code is written, but the `this` would work the same way as far as i know. – Abhinav Galodha Feb 02 '17 at 20:35
  • I get to know that the actual problem was just using of arrow function and functions without binding this. – sagar Feb 06 '17 at 18:35
0

This is because the context of this is different for the inner function.

Try:

socketEvents()
{
    this.io.on('connection',(socket) => {
        socket.on('send message',function(data)
        {
            socket.emit('new message',data);//here the error lies.
        });
    }); 
}
Mithilesh Gupta
  • 2,800
  • 1
  • 17
  • 17
  • you are right but your answer doesn't make sense as it doesn't provide the solution for using "this" inside socket.on. It just provides an alternate way which is not useful in my case. As I have to use "this" keyword (mandatory). – sagar Feb 06 '17 at 18:38
0

use io.emit() instead of socket.broadcast.emit()

io.on('connection', function(socket){
  socket.broadcast.emit('request', /* */); 
  io.emit('broadcast', /* */); 
  socket.on('reply', function(){ /* */ }); 
});
KARTHIKEYAN.A
  • 18,210
  • 6
  • 124
  • 133