

Zones – Robust error handling and flow control for Node.js - piscisaureus
http://strongloop.com/strongblog/announcing-zones-for-node-js/

======
reissbaker
Looking through the Zone API documentation, this is a reimplementation of what
most Promise libraries already provide (Zones even support "then" and "catch"
methods, but don't follow the chaining standard). The only new feature is
"Gates," which the documentation admits are awkward and need to be revisited —
and many Promise libraries already provide simple mechanisms for sharing
resources similar to what Gates allow, but with more-consistent APIs. Zones
also don't work several important Node-core libraries (cluster, fs, zlib, and
more), whereas Promise libraries solved interop long ago.

Promises/A+ is already standardized and is shipping in browsers. Yes,
Promises/A+ is more complicated than it needs to be, and I wish a simpler,
more monadic approach had won out. But this is an unnecessary flow-control
fork, and it's not even a particularly good one by comparison. If Zones were
built on top of the ES6 standard, all ES6-compatible promise libraries would
immediately work with it (and there are many mature ones that already exist).
No existing libraries work with Zones, and the existing ones will need to be
amended to add Zone-specific interop.

God knows nobody needs a zone-to-promise converter; there are enough ways to
do asynchronous flow control as it stands. This blog post seems to hope that
Zones will some day make it into Node core; I sincerely hope they don't in
their current state.

~~~
piscisaureus
I'm sorry if it wasn't clear enough from the blog, but the attempt here is not
to write a flow control library that solves the callback hell problem like
promises does.

You should think of it more as an asynchronous try-catch block, where
resources created in the "try" block are automaticially cleaned up.

I believe that flow control in the future will be done with generators; check
out [https://github.com/visionmedia/co](https://github.com/visionmedia/co) for
example.

~~~
reissbaker
Okay. But Promises _already_ provide asynchronous try/catch blocks, and you
could have used those as the basis of your API (and as first-class objects
that get returned), rather than inventing a new API and set of objects.

> I believe that flow control in the future will be done with generators;
> check out
> [https://github.com/visionmedia/co](https://github.com/visionmedia/co) for
> example.

Generators and promises are both types of flow control that will be used in
the future: they're both in the ES6 standard. In fact, visionmedia/co already
supports promises.

~~~
piscisaureus
A Zone object could be a "subclass" of a Promise. It's something I have
considered but I didn't think it'd be necessary for the first release.

> But Promises already provide asynchronous try/catch blocks

They do, if all you use is modules that return promises, and the node
ecosystem currently has many modules that don't. For example:

    
    
        zone.create(function MyZone() {
          // Within MyZone
          setTimeout(function() {
            // Within MyZone
            throw new Error("Oh noes!");
          });
        }).catch(function(err) {
          // Back in the parent zone.
          // Handle the error here.
        });
    

The above won't work with promises unless you use a promisified version of
setTimeout _and_ return that promise from the constructor function.

Conversely, with zones, chaining callbacks is hard to define conceptually:

    
    
        zone.create(function MyZone() {
          // In MyZone
        }).then(function() {
          // Which zone are we in?
        }).then(function() {
          // Which zone are we in?
        });
    

But if you have a great idea here, bring it on.

~~~
reissbaker
From an admittedly brief look through the source, it looks like the zone
module does two things:

1\. Creates the "Zone" and "Gate" abstractions, and, 2\. Monkeypatches Node to
use Zones and Gates.

To make setTimeout work, the zone module monkeypatches global.setTimeout and
replaces it with a version that uses Zones and Gates. Rather than do that,
what you could do is not use Zones and Gates at all, and monkeypatch
global.setTimeout and replace it with a version that uses Promises. And:
there, Promises work with setTimeout. Just as easily as Zones and Gates do.

(Alternatively, what many Promise libraries do is offer ways to generate
"promisified" versions of individual non-Promise functions and encourage you
to call those instead, rather than monkeypatching globals.)

My objection to zone is just the new abstractions, Zones and Gates. They don't
seem to offer much (anything?) over Promises, and they seem needlessly
incompatible with them. Instead of the two-part module, where you introduce
Zones and Gates and also monkeypatch everything to use them, you could just
have a one-part module that monkeypatches everything to use Promises. It would
be less code and it would interoperate with the existing JS ecosystem.

I don't have a particular love for the Promise abstraction: it's just that
everyone is going to have to learn and work with Promises anyway (since
they're in ES6, and already in V8), and there's no reason to invent a new
abstraction for asynchronous try/catch when one already exists. There are lots
of Promise-supporting libraries, and no Zone-and-Gate-supporting ones, save
for zone itself. Why bother with the fork?

------
stormbrew
I'm having a really hard time seeing how this is an actual improvement on the
status quo. It just seems to build up a lot of complexity and create new and
more confusing corner cases. I have a hard time following the demos, even with
copious comments, and one of them even has a null exception catch and calls it
a good thing (the http long stack demo).

~~~
piscisaureus
> I'm having a really hard time seeing how this is an actual improvement on
> the status quo

What we're doing is make it unnecessary to add error handlers everywhere and
still get caught by surprising failure modes. If the zone catches an error it
cleans up (closes resources, cancel operations when that makes sense) and then
routes the error to the zone's result callback so you can handle it in once
place.

The 'status quo' is that node has domains, but zones should be conceptually
cleaner and thus have less corner cases.

> one of them even has a null exception catch

I'm not sure what you mean here. The http demo catches an exception and prints
the stack trace. We can do that because the zone cleans up the socket so it's
not necessary to exit and restart node.

~~~
munro
The comparison page highlights that Zone.js is better than promises because of
long stack traces [1], but most promise implementations already have that [2].
I'm confused, that seems to be the only comparison to promises.

Edit: Conceptually it seems the same as promises. The main difference seems to
be that they've added hooks [3] into the pipeline, and they duck punch the
core API to intercept errors. Bluebird has solved this without duck punching
using `Promise.promisifyAll(require("fs"))` [4]. I would love to see a write
up on Zone.js's forks, because the article could of trivially been rewriten to
use promises.

[1] [http://strongloop.com/strongblog/comparing-node-js-
promises-...](http://strongloop.com/strongblog/comparing-node-js-promises-
trycatch-zone-js-angular/) [2] [https://github.com/kriskowal/q#long-stack-
traces](https://github.com/kriskowal/q#long-stack-traces) [3]
[https://github.com/btford/zone.js/#zonefork](https://github.com/btford/zone.js/#zonefork)
[4]
[https://github.com/petkaantonov/bluebird](https://github.com/petkaantonov/bluebird)

~~~
piscisaureus
Note that the comparison page doesn't have the "zone" library we just
announced on it. Zone.js is conceptually a bit different and it targets
browsers.

------
orand
I highly recommend listening to JavaScript Jabber's Zone.js interview [1] with
Brian Ford that came out yesterday. He mentions collaborating with this NodeJS
Zones project and the possibility of convergence.

I also recommend watching his ng-conf talk [2] on Zone.js to get a better
understanding of what zones enable.

[1] [http://javascriptjabber.com/110-jsj-zones-with-brian-
ford/](http://javascriptjabber.com/110-jsj-zones-with-brian-ford/)

[2]
[https://www.youtube.com/watch?v=3IqtmUscE_U](https://www.youtube.com/watch?v=3IqtmUscE_U)

------
bajtos
> We’re waiting eagerly for node v0.12 to be released. > Unfortunately, the
> release may not happen soon since there are about 800 open bugs and about
> 180 pull requests waiting to be reviewed.

Is it a real problem? Seems that other popular projects like Ruby on Rails
have a similar number of opened issues and it's not stopping them from
releasing new versions.

Does the Node core team have any plans how to prevent this situation in the
future?

~~~
james33
That quote and those numbers are incredibly misleading, I'm not sure why they
use that to prove Node 0.12 isn't coming soon. If you actually look at the
issues on Github, only around 30 of those are marked as 0.12, with the rest
being various other milestones including 0.13 and 1.0. It has also already
been stated that there is only one more 0.11 release before 0.12.

~~~
octetcloud
No one is trying to "prove" 0.12 isn't coming soon, we've put lots of work
into it, and look forward to its release, and its got some great new features.

I'm not sure the tag states are always up to date, perhaps they are, but the
fact remains that 0.12 has been "real soon now" for quite a while, so saying
it might be a while still is a pretty safe statement.

The core team is working hard, but I think the PR queue is a good indication
of how scarce a resource review time is.

~~~
james33
The way it is stated assumes that 0.12 won't be coming until all issues and
pull requests are closed, which clearly is not the case.

------
ypcx
Any error handling that forces me to add extra lines into my code is one I see
as too obstructing. First and foremost, asynchronous exception handling and
propagation, and "long" stacktraces that go with it, should be a core part of
the JavaScript language, and I'm personally waiting for that to happen at some
point. In the meantime, the best solution I was able to come up with is
"LAEH2". See it here:
[https://github.com/ypocat/laeh2](https://github.com/ypocat/laeh2)

