Skip to content

Instantly share code, notes, and snippets.

@benjamingr
Last active December 27, 2015 11:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save benjamingr/7319658 to your computer and use it in GitHub Desktop.
Save benjamingr/7319658 to your computer and use it in GitHub Desktop.

Traditionally, JavaScript code contains some sort of asynchronous logic either on the client side or on the server side.

This makes the try/catch construct non-practical for many real use cases because it can not catch errors caused by callbacks and/or other asynchronous operations involved. This is why we have common idioms like the (err,result) of NodeJS callbacks or reject in promises implementations and so on.

NodeJS also introduces domains which let you catch all errors that originated from a piece of code in a certain way.

ES6 Generators recently implemented in NodeJS allow us to do concurrency using coroutines. This allows for very nice code that's very readable in certain cases. The async_functions proposal is also very interesting solving the problem without needing a "runner" for the generator.

However, one issue arises from using generators for such concurrency. The current way try/catch works with generators does not give us a way to differentiate things like syntax errors from logic errors.

Consider the following piece of code using Bluebird promises:

Promise.coroutine(function *(){
    try{
        let db = yield DBEngine.open("northwind");
        let result = yield db.query("SELECT name FROM users")
        return res;
    } catch (e){
        //code to handle exception in DB
    }
});

Noticed the ReferenceError? Not obvious at first glance. A compile time tool might find it but I may have a closure variable named res. This might even happen later when making changes. A catch-all does not do a good job here. What I'd want to do is to catch all exceptions that are mine. I need a way to catch exceptions of a different type.

This is a real need in light of the new found usage for try/catch given generators.

I've looked around and found one possible solution using catch guards ( http://wiki.ecmascript.org/doku.php?id=strawman:catch_guards ) , I know Firefox supports catch guards but I was unable to find anything in the specification or in the mailing list when searching relating to it.

@petkaantonov
Copy link

Without predicated catch clauses you would need to write something like this:

Promise.coroutine(function *(){
    try{
        let db = yield DBEngine.open("northwind");
        let result = yield db.query("SELECT name FROM users")
        return res;
    } catch (e) {
        if( e instanceof RejectionError ) {
            //code to handle exception in DB
        }
        else {
            throw e;
        }

    }
});

The manual rethrow can easily be forgotten to be written

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment