sagar
sagar

Reputation: 732

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>

Upvotes: 7

Views: 29786

Answers (3)

KARTHIKEYAN.A
KARTHIKEYAN.A

Reputation: 20118

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

io.on('connection', function(socket){
  socket.broadcast.emit('request', /* */); 
  io.emit('broadcast', /* */); 
  socket.on('reply', function(){ /* */ }); 
});

Upvotes: 0

Abhinav Galodha
Abhinav Galodha

Reputation: 9898

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?

Upvotes: 7

Mithilesh Gupta
Mithilesh Gupta

Reputation: 2930

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.
        });
    }); 
}

Upvotes: 0

Related Questions