
JavaScript Promises: There and back again - sacado2
http://www.html5rocks.com/en/tutorials/es6/promises/#!
======
jeswin
Broader adoption of JS on the server will only begin after ES6 generators land
in Node. Due to the complexity of async code, writing JS on the server is not
easy for the average team.

As of now, you could use Promises but it is still kind of messy without
generators. Here is a simple example:

    
    
      #Without generators
      Credentials.get({ token })
          .then (credentials) =>
              User.get({ username: credentials.username })
    
      #With generators
      credentials = yield Credentials.get({ token })
      User.get({ username: credentials.username })
    

We use FaceBook's regenerator project to compile ES6 features down to Node's
currently supported Javascript features. If you don't want to use the
--harmony flag, you should really try it out.
[https://github.com/facebook/regenerator](https://github.com/facebook/regenerator)

~~~
camus2
Good but can you yield from the global scope? if not you still need to write
at least a function.

The hardest stuff in JS is that :

    
    
        function F(){throw "error"}
    
       try{setTimeout(F,1000)}catch(error){ console.log("error")}
    

we cant catch async errors outside the async callback , will generators fix
this ? ( by the way , that's why you should never throw any error yourself in
js ).

~~~
domenicd
You cannot yield from the global scope; you have to explicitly be inside a
generator function. This isn't really a problem in practice except for one-
off-scripts, since most modules don't have side effects but instead export
functions (possibly generator functions). But for those one-off scripts it is
indeed a bit awkward... you could imagine ways to get around it.

You can catch async errors with generators and promises; see e.g. the linked
post, or [http://jlongster.com/A-Study-on-Solving-Callbacks-with-
JavaS...](http://jlongster.com/A-Study-on-Solving-Callbacks-with-JavaScript-
Generators)

------
fishtastic
I recently found that AngularJS has supports for promises. I replaced some of
the callback code to use promises and it's a lot more readable.

Callbacks:

    
    
        Backend.CallA(param, function() { 
          aDone = true;
          if (aDone && bDone) { doC(); }
        });
        Backend.CallB(param, function() { 
          bDone = true;
          if (aDone && bDone) { doC(); }
        });

Promises:

    
    
        var promiseA = Backend.CallA(param);
        var promiseB = Backend.CallB(param);
        $q.all([promiseA, promiseB]).then(doC);

~~~
danabramov
IIRC Angular's promises are based on stripped down version of Kris Kowal's Q.
You may want to check it out:

[https://github.com/kriskowal/q](https://github.com/kriskowal/q)

~~~
jeremya
As of AngularJS version 1.2, the promises provider ($q) is fully Promises/A+
compliant.

[http://blog.angularjs.org/2013/11/angularjs-120-timely-
deliv...](http://blog.angularjs.org/2013/11/angularjs-120-timely-
delivery.html)

------
iamwil
What version of Javascript has Promises and does anyone know the estimated
time it might take to make it over to V8 and subsequently node.js?

The biggest issue I had with promises is interfacing with non-promise code.
There are methods to 'lift' node.js code that uses callbacks into promises,
but the resulting code is much noiser.

I'm a bit disappointed that the official JS version didn't cut down on the
visual noise of the piping so the actual work being done stands out. Maybe
there needs to be a different type of syntax highlighter that mutes the
promises piping and highlights the actual calls.

~~~
astrodust
I've just been using the Q promise library and it works fine in NodeJS. The Q
wrappers for NodeJS style functions is a bit ugly, but it works very well.

The real problem is the core NodeJS libraries aren't promise compliant. I
don't know if there's a module that cleanly wraps all of these in their
promise analogs but that'd be the best thing here.

Calling Q.nsend() on everything is messy, but is a lot better than dealing
with ridiculously nested callbacks.

~~~
mjackson
> The real problem is the core NodeJS libraries aren't promise compliant.

This isn't a problem at all in practice.

To say that node core is not "promise compliant" gives people the idea that
there is something that prevents them from using promises in node. In reality,
most promise libraries have a "denodeify" function that will convert any
function that expects a node-style callback into one that returns a promise
instead.

    
    
      var fs = require('fs');
      var rsvp = require('rsvp');
      
      // Create a version of fs.readFile that returns
      // a promise instead of expecting a callback.
      var readFile = rsvp.denodeify(fs.readFile);
      
      readFile('/etc/passwd', 'utf8').then(function (contents) {
        // do something with the file contents
      }, function (error) {
        // handle the error
      });
    

It is similarly easy to convert functions that expect other types of callbacks
(read: not node-style callbacks where the first argument is always an error)
to functions that return promises using deferreds.

~~~
astrodust
That's a good pattern, but obnoxious to apply on large numbers of functions.
If something just did this for you in advance, that'd be what I'm looking for.

Trouble is, NodeJS set a convention and now everyone adheres to it. I'm not
complaining there's standards, in fact that's a good thing. Part of me is just
disappointed that the promise standardization happened too late in the game
for NodeJS to build around it.

~~~
spion
It really isn't much of a problem. A lot of the time its as easy as replacing

    
    
      var lib = require('lib');
    

with (given var Promise = require('bluebird'))

    
    
      var lib = require('lib');
      Promise.promisifyAll(lib);
    

And in case of classes, you'd use promisifyAll on about 2-3 prototypes
instead.

------
programminggeek
Interesting. I found that TameJS or Iced CoffeeScript mostly solved the async
terribleness problem in node, but you basically are using a non-standard
toolchain at that point, and setting that up for a whole team is sort of
absurd.

Also, I'm not fully convinced that node is worth the code complexity that all
of these solutions bring with them when go or scala can give you better
performance with much cleaner code.

------
atrilumen
I've been really enjoying ToffeeScript, which provides implicit continuations.
It was trivial to implement coroutines on top of it:
[https://gist.github.com/luciangames/7776345](https://gist.github.com/luciangames/7776345).

It works very well if you bear in mind what's happening to the call stack. In
my case, every call to pause! or wait! is scheduling a continuation to be
called later by the game loop. If I'm not mistaken, the overhead of each
continuation is just that of a closure.

It's very comfortable, coming from a background in Stackless Python, Lua, and
Unity.

I wish more people would take a look at ToffeeScript.

------
tlrobinson
Fantastic! I don't know if promises are the ultimate solution to async
programming, but they're a hell of a lot better than plain old callbacks.

------
ajtaylor
Unrelated to the article content, I just noticed the table of contents on the
left side. The slow fade in/out when you mouse over it is perfect! It's fixed
position so you always see it, yet it's totally unobtrusive while reading the
article. Brilliant!

------
davej
Slightly off-topic but the new HTML5Rocks site is much more responsive and
easier to read.

~~~
jbigelow76
Agreed, it looks great. I was poking around the site hoping to find a link to
a Bootstrap-esque code repository of the base HTML and CSS.

~~~
rcsorensen
[https://github.com/html5rocks/www.html5rocks.com](https://github.com/html5rocks/www.html5rocks.com)

Is that what you were looking for?

The article linked looks to be at
[https://github.com/html5rocks/www.html5rocks.com/blob/master...](https://github.com/html5rocks/www.html5rocks.com/blob/master/content/tutorials/es6/promises/en/index.html)
.

~~~
jbigelow76
I didn't realize the entire site was on github (obviously I didn't realize any
of the site was on github to be honest). Thanks so much for the links.

------
arbesfeld
Hopefully we will see ImageBitmaps soon:

[http://www.whatwg.org/specs/web-apps/current-
work/multipage/...](http://www.whatwg.org/specs/web-apps/current-
work/multipage/timers.html#imagebitmap)

------
pablovidal85
Call me crazy, but I fail to see the improvement in this weird syntax and I've
had enough. Go, there we go.

~~~
tlrobinson
Composibility and error handling.

~~~
pablovidal85
I have that already with libraries like caolan/async and node.js convention of
first-argument-error + callbacks. Now, of course I would like to have that
features natively, but not at the cost of having more (ugly) syntax. My point
is that if I have to learn new syntax, I would then use the time to learn a
modern and efficient new programming language.

------
thrush
does this mean anything for NodeJS programmers that rely on an existing
promise library (eg Q)?

~~~
PhrosTT
Well presumably this makes it's way into V8 and therefore node. I'd assume the
performance is better than Q.

The biggest issue for me is Q's habit of hiding errors despite me defining a
Q.onerror handler. Hopefully a native implementation would fail a little
louder.

~~~
iamwil
I've had this issue with Q and when. Sometimes, things would fail inside a
then chain, and then I can't figure out where exactly it failed, because
though it fell through a couple thens, I'm not sure exactly where it came
from, or how it got that way.

~~~
stu_k
Have you tried setting

    
    
        Q.longStackSupport = true
    

? This is invaluable for debugging (although it does slow things down a lot,
so don't use it in production)

~~~
spion
Yep, and this is exactly why its so nice to have promises built into the
language. That way, the implementing engine could provide long stack traces
for them as well as extra inspection and tooling of all currently pending
async operations - and it could do that at the lowest possible performance
cost.

------
kretor
Are there tools that visualize code as a flowchart, like he did halfway
through the tutorial?

------
itsbits
does latest NodeJS has this?

~~~
jonsherrard
npm install es6-promise for a shim

