
Comparing Node.js Promises, Try/Catch, Angular Zone.js and Zone - alexgorbatchev
http://strongloop.com/strongblog/comparing-node-js-promises-trycatch-zone-js-angular/
======
ulisesrmzroche
Generators are the best, though I'm starting to worry I'm using them too much.

edit: I'm using koa, so co is working in the background here. Should have said
that earlier, my bad.

var save = function*(){ try { yield db.insertUser(); } catch (e) { throw e; }
}

~~~
bajtos
That's not entirely true. If "db.insertUser()" is opening a database
connection, who is going to close it on error?

The idea behind Zones for Node.js is to auto-attach new resources to the
current zone, so that they can be cleaned when the zone exits.

AFAIK there is no solution for that at the moment.

~~~
ulisesrmzroche
I'm thinking whatever db plugin you're using, but also this pseudo code
actually has a lot of implicit things going in the background (koa/co, thunks,
etc).

It makes for some readable app code though.

------
spankalee
One thing missing from this picture is Streams - the multivalued analog to
Promises (Futures in Dart). The button click example would be quite easy to
handle, even without Zones, if the button had an onClick event stream, rather
than taking a callback.

This code, which doesn't work as intended:

    
    
      function thirdPartyFunction() {
         function fakeXHR() {
           throw new Error("Invalid dependencies");
         }
     
        setTimeout(fakeXHR, 100);
       }
     
      function main() {
         button.on("click", function onClick() {
           thirdPartyFunction();
         });
       }
     
      main();
    

would instead look like this with a Streams-based API (I'm assuming a Dart-
like API, since I don't know the proposed Stream API for JS):

    
    
      function thirdPartyFunction() {
         function fakeXHR() {
           throw new Error("Invalid dependencies");
         }
     
        setTimeout(fakeXHR, 100);
       }
     
      function main() {
         button.on("click")
           .listen(function onClick() {
             thirdPartyFunction();
           })
           .onError(function onError() {
             console.log("now it works with errors");
           })
       }
     
      main();
    

Since onClick is executed by the Stream, even a synchronous exception in
thirdPartyFunction will be caught and given to the onError callback.
JavaScript could really use a better DOM API with Promises and Streams in
place of most callbacks. I think most of the Streams work is here:
[https://github.com/whatwg/streams](https://github.com/whatwg/streams)

So Zones aren't really needed here. They are very useful though. AngularDart
uses them to intercept any external trigger of the event loop so that it can
run it's change detection code (this is why they ported Zones to JavaScript).
Dart's unittest library runs each test in a Zone to wait for outstanding
microtasks and catch async errors that might happen after a test appears to
have completed and associate it with the correct test. And of course using
Zones to string together async stack traces or debugging is invaluable.

------
olalonde
The author does not seem like an experienced Node.js developer. All those

    
    
        if (err) {
          done(err);
        }
        else {
          // ...
        }
    

are usually written in this style:

    
    
       if (err) return done(err);
       // ...
    

I personally don't like promises and tend to avoid libraries who use them. I
don't really see the problem they are trying to solve which is not already
solvable in a more flexible way through libraries like async.

~~~
alexgorbatchev
I agree that libraries should not be handling errors in any unusual way, or
better yet just re/throw them and let consumer take care of that. That's where
the promises/zones might be useful.

~~~
olalonde
Right. I don't mind if people want to use promises in their own code as long
as they don't force their use on library users.

------
inglor
Cute, although if you promisify all your async primitives promises are throw
safe and the Bluebird library makes this really easy.

I hope they're able to get to as fast as Bluebird performance , which is
almost as fast as callbacks and faster than the async module.

------
dharbin
q.js can properly handle exceptions thrown in a handler. see the examples
here:
[https://github.com/kriskowal/q#chaining](https://github.com/kriskowal/q#chaining)

~~~
rymohr
So can when.js which has become my favorite promises library:

[https://github.com/cujojs/when](https://github.com/cujojs/when)

[http://know.cujojs.com/tutorials/async/mastering-async-
error...](http://know.cujojs.com/tutorials/async/mastering-async-error-
handling-with-promises)

------
eldude
> Up until recently that was pretty much all we had.

[Edit: see my comment below[0]. This is more a coincidence of wording than a
StrongLoop marketing line]

When StrongLoop talked at my south bay node.js meetup group, BayNode[1], at
Hacker Dojo last month, they demoed Zone.js. Before demoing though, they asked
if anyone in the group had "solved this" to which I made it very clear that,
"Yes, I did about 2 years ago with trycatch[2]." Their response could be
summed up as, "Oh?"

Long story short, not only does my async try/catch library solve this, I can
say with near certainty that it solves it in a better, more consistent, more
tested, more battle proven, more performant manner. We use trycatch at
LinkedIn and have not had to worry about async error handling since.

Additionally, adding it to any control-flow of your choice is trivial, as I
have done with my stepup library[3]. Further, their main bullet-points are
about enforcing the callback contract, something EVERY control-flow library
should be doing, (I previously went into more detail here[4]) and the primary
reason for the popularity of promises since they formalized this contract.

In fact, I teach these core contract rules in my monthly week-long node.js
bootcamp I give here at LinkedIn[5], and the only thing they have to do with
control-flow is that your control-flow library of choice should enforce them,
as stepup and promises do. I do add a few rules:

* Function that takes 2 arguments: 1. first argument is an error, 2. second argument is the result, 3. Never pass both, 4. error should be instanceof Error

* Must never excecute on the same tick of the event loop

* Must be passed as last argument to function

* Return value is ignored

* Must not throw / must pass resulting errors

* Must never be called more than once

Long story short, domains are broken, try/catch is insufficient, use trycatch
because I solved this problem over 2 years ago and have been perfecting it
since.

[0]
[https://news.ycombinator.com/item?id=7598983](https://news.ycombinator.com/item?id=7598983)

[1] [http://www.meetup.com/BayNode/](http://www.meetup.com/BayNode/)

[2]
[https://github.com/CrabDude/trycatch](https://github.com/CrabDude/trycatch)

[3] [https://github.com/CrabDude/stepup](https://github.com/CrabDude/stepup)

[4]
[https://news.ycombinator.com/item?id=7020054](https://news.ycombinator.com/item?id=7020054)

[5]
[https://gist.github.com/CrabDude/10907185](https://gist.github.com/CrabDude/10907185)

~~~
bilalq
This seems really cool! I'm surprised I haven't heard about this until now.

However, this solution seems to be Node specific. The example where they
lament about how this "was pretty much all we had" was about a browser error.
Angular's Zone.js seems to be the closest project to solving the problem in
that context.

~~~
eldude
Ah, sorry then for my strong rebuke. I am making the incorrect assumption then
that this was a StrongLoop marketing line, not a coincidental similarity.

~~~
bilalq
You should write a blog post about this. There are a lot of parallel efforts
going on to bring sanity to async errors in JS, and it would be great to see
what the outcome of cross-pollinating these ideas would be.

