javascript - try catch not working in Node socket.io listener - Stack Overflow

admin2025-04-20  1

I am working on an app that involves the use of WebSockets. I have the following code as a part of the application:

io.on('connection', socket => {

   let PLAYER = {};

   // Listener for event 1
   // Listener for event 2
   // ...

   socket.on('setName', ({name, role, room}) => {

        PLAYER.name = name;
        PLAYER.role = role;
        PLAYER.room = room;

        try{
            joinRoom(PLAYER);  // This function can throw an error
            socket.emit('roomJoin');
        }catch(e){
            socket.emit('error', e.message);
            return;
        }
    });
});

Now, when the joinRoom function does throw an error, Node just crashes with the following exception:

events.js:306
    throw err; // Unhandled 'error' event
    ^

Error [ERR_UNHANDLED_ERROR]: Unhandled error. ('error message')

The error event is never emitted. What has made the try catch block fail?

Note: I am using TypeScript, but have removed type declarations in the above snippet as they shouldn't have anything to do with the problem.

Edit 1:

I have recreated the issue with simpler code as follows:

import express from 'express';
import socketio from 'socket.io';
import http from 'http';

const PORT = process.env.PORT || 8000;

const app = express();
const server = http.createServer(app);
const io = socketio(server);

server.listen(PORT, () => {
    console.log(`Listening on port ${PORT}`);
});

const checkLength = (bar) => {
    if(bar.length > 14){
        throw Error('word is too long!');
    }
    // ...
}

io.on('connection', socket => {
    console.log('new socket connection');

    socket.on('foo', ({bar}) => {
        try{
            checkLength(bar);
        }catch(e){
            socket.emit('error', e.message);
            return;
        }
        console.log('app did not crash!');
    });
}

When the length of bar is greater than 14, the app crashes with the same error mentioned above.

I am working on an app that involves the use of WebSockets. I have the following code as a part of the application:

io.on('connection', socket => {

   let PLAYER = {};

   // Listener for event 1
   // Listener for event 2
   // ...

   socket.on('setName', ({name, role, room}) => {

        PLAYER.name = name;
        PLAYER.role = role;
        PLAYER.room = room;

        try{
            joinRoom(PLAYER);  // This function can throw an error
            socket.emit('roomJoin');
        }catch(e){
            socket.emit('error', e.message);
            return;
        }
    });
});

Now, when the joinRoom function does throw an error, Node just crashes with the following exception:

events.js:306
    throw err; // Unhandled 'error' event
    ^

Error [ERR_UNHANDLED_ERROR]: Unhandled error. ('error message')

The error event is never emitted. What has made the try catch block fail?

Note: I am using TypeScript, but have removed type declarations in the above snippet as they shouldn't have anything to do with the problem.

Edit 1:

I have recreated the issue with simpler code as follows:

import express from 'express';
import socketio from 'socket.io';
import http from 'http';

const PORT = process.env.PORT || 8000;

const app = express();
const server = http.createServer(app);
const io = socketio(server);

server.listen(PORT, () => {
    console.log(`Listening on port ${PORT}`);
});

const checkLength = (bar) => {
    if(bar.length > 14){
        throw Error('word is too long!');
    }
    // ...
}

io.on('connection', socket => {
    console.log('new socket connection');

    socket.on('foo', ({bar}) => {
        try{
            checkLength(bar);
        }catch(e){
            socket.emit('error', e.message);
            return;
        }
        console.log('app did not crash!');
    });
}

When the length of bar is greater than 14, the app crashes with the same error mentioned above.

Share Improve this question edited Sep 15, 2020 at 6:03 ml23 asked Sep 15, 2020 at 5:23 ml23ml23 771 silver badge9 bronze badges 10
  • Are you potentially missing catch statements on the .on events? I.e. io.on('connection', socket => {}).catch((err) => {}) ?. Which websocket library are you using? – Phobos Commented Sep 15, 2020 at 5:28
  • @Phobos I'm using socket.io. I don't have a catch statement for the io.on('connection') event, but try-catch blocks in other events I'm listening works - just not this one, which is strange. – ml23 Commented Sep 15, 2020 at 5:36
  • 1 @Phobos The on method doesnt have error handling on its own. What could be an issue is if joinRoom is calling an async function that's not being await-ed. If the Promise or async function, errors, it cannot be caught with a recular try-catch block, unless an await is done. – Mike Commented Sep 15, 2020 at 5:36
  • I agree with @Mike, joinRoom is likely an async function so you need to catch the error using joinRoom().catchError(error => /* handle error here */). – bloo Commented Sep 15, 2020 at 5:50
  • 1 Much much appreciated. Although, the issue was staring at us in plain sight all along. I've added my answer. – Mike Commented Sep 15, 2020 at 6:25
 |  Show 5 more ments

3 Answers 3

Reset to default 4

After replicating the server on my local machine, I realized you were calling emit on a reserved keyword for socket.io. When you call socket.emit('error', e.message), there is an expected listener to exist. One like this:

socket.on('error', err => {
  // An error occurred. 
})

You should use a different phrase for your emit. I personally use oops on my socket servers. socket.emit('oops', {error}). You can read more about error handling on their page.

To add, socket.emit('error') does not pass the error or any data down to the client and instead is handled by the server, which is why you need to use a different phrase.

You can use the promisses, and than you can profite from the then() method which also returns a Promise. It takes up to two arguments: callback functions for the success and failure cases of the Promise.

So your code should be something like this:

import express from 'express';
import socketio from 'socket.io';
import http from 'http';

const PORT = process.env.PORT || 8000;

const app = express();
const server = http.createServer(app);
const io = socketio(server);

server.listen(PORT, () => {
    console.log(`Listening on port ${PORT}`);
});

const checkLength = (bar) => {
  return new Promise((resolve, reject)=>{
    if(bar.length > 14){
      // throw Error('word is too long!');
      reject('word is too long!')
    } else {
      resolve('app did not crash!')
    }
  });  
}

io.on('connection', socket => {
  console.log('new socket connection');
  socket.on('foo', ({bar}) => {
    checkLength(bar).then((result) => {
        console.log('app did not crash!');
    }).catch(err => {
      console.log("app did crash with this error:", err);
    });
  });
}

I noticed you hadn't initialized your PLAYER variable.

let PLAYER = {};

#EDIT 1:

try also adding an error handler for your socket server and log it to get an idea of what is causing the error.

socket.on('error', (error) => {
  console.log(error);
});
转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1745116247a285878.html

最新回复(0)