sagar sagar - 4 years ago 250
Javascript Question

TypeError: Cannot read property 'emit' of undefined

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>

Answer Source

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?

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download