Search code examples
node.jsexceptioneventshandle

nodejs handle exception in events handler: safeway?


There is another true way, to do safe handle exceptions in nodejs events unsafe handlers? I can't control event handlers, but application must run after errors in it.

var someUnsafeEventHandler = function(){ throw "throw!"; };

var MySafeEventHandler = function(f){
    return function(){
        try{ 
            f.apply(f,arguments);
        }catch(e){
            console.warn("MySafeEventHandler handle error: "+e);
        };
    }
}

var EventEmitter = require('events');
var myEmitter = new EventEmitter();

myEmitter.on('event', new MySafeEventHandler(someUnsafeEventHandler));
myEmitter.on('event', someUnsafeEventHandler);

console.log("== start test ==");
myEmitter.emit('event');
console.log("== test passed =="); // never printed by exception in someUnsafeEventHandler

output:

== start test ==
MySafeEventHandler handle error: throw!

/tmp/test_events.js:5
var someUnsafeEventHandler = function(){ throw "throw!"; };
                                         ^
throw!

Solution

  • It's a bad practice to swallow errors, so it's better to redirect errors to a special error event defined in EventEmitter.

    var someUnsafeEventHandler = function(){ throw "throw!"; };
    
    const safeHandler= (f)=> function(){
        try{
            f.apply(this, arguments);
        }catch(e){
            this.emit('error', e);
        }
    }
    
    var EventEmitter = require('events');
    var myEmitter = new EventEmitter();
    
    // catch errors
    myEmitter.on('error', e=> console.log(`Caught: ${e}`));
    
    myEmitter.on('event', safeHandler(someUnsafeEventHandler));
    myEmitter.on('event', ()=> console.log('second listener'));
    
    console.log("== start test ==");
    myEmitter.emit('event');
    console.log("== test passed ==");
    

    Output:

    == start test ==
    Caught: throw!
    second listener
    == test passed ==
    
    Process finished with exit code 0