I am using callbacks with socket.io
Client code :
socket.emit('someEvent', {data:1}, function(err, result) {
console.log(err.message);
});
Server code :
socket.on('someEvent', function(data, callback) {
callback(new Error('testing error'));
});
With the above code the client side always prints out undefined. If I change the server side code to the following I can see the error message.
socket.on('someEvent', function(data, callback) {
callback({message:'testing error'});
});
I can pass my own custom objects to the client just fine, just not the error object. Any ideas?
socket.io data is serialized as JSON, which can only represent plain objects. You will need to serialize any errors into a recognizable plain-object format, or let Socket.IO's standard serialization do its thing (which will result in a plain empty object for Error instances.
I also think it's odd that Socket.IO doesn't seem to provide explicit built in support for passing Error objects in a meaningful way.
If you want to have Error objects seralized correctly in Socket.IO callbacks you can define a method like this to specify how serialization with .toJSON for Error messages should be handled:
if (!('toJSON' in Error.prototype)) {
Object.defineProperty(Error.prototype, 'toJSON', {
value: function () {
let result = {}
Object.getOwnPropertyNames(this).forEach((key) => {
if (key === 'stack') return
result[key] = this[key];
}, this)
return result
},
configurable: true,
writable: true
})
}
If you are throwing messages from the server you will want to define this on the server, and if throwing errors from a client to the server you will need to define it on the client too.
Note: In this example it strips the 'stack' property when returning errors to the client (to avoid exposing internals to a client), but this may be something worth leaving in, at least for development mode.
Adapted from a blog post I wrote recently on this:
https://medium.com/@iaincollins/error-handling-in-javascript-a6172ccdf9af
I'm happy to say this easier/cleaner with ES6.
If you define your class extending Error like this:
class ValidationError extends Error {
constructor(message) {
super(message)
this.name = 'ValidationError'
this.message = message
}
toJSON() {
return {
error: {
name: this.name,
message: this.message,
stacktrace: this.stack
}
}
}
}
Instead of this being the object that gets passed back:
{ name: 'ValidationError' }
It now looks something like this:
{
error: {
name: 'ValidationError',
message: 'A validation error',
stacktrace: '…'
}
}
You can see what to expect by doing this:
console.log(JSON.stringify(new ValidationError('A validation error'))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With