Skip to content Skip to sidebar Skip to footer

How To Pass Error Object To Socket.io Callback

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

Solution 1:

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.

Solution 2:

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'inError.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.

Update: This is a lot easier with ES6

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:

classValidationErrorextendsError {
  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(newValidationError('A validation error'))

Solution 3:

Here's a little router function that works with plain error objects. You might want to remove the stack variable if you're shy.

socket.on('api', async (method, args, callback) {
  try {
    const result = await api[method](...args)
    callback(null, result)
  } catch (error) {
    const { name, message, stack } = error
    callback(error.toJSON ? error : { name, message, stack })
  }
})

Post a Comment for "How To Pass Error Object To Socket.io Callback"