

Write logic, not mechanics - vgnet
http://jeditoolkit.com/2012/04/26/code-logic-not-mechanics.html

======
sergimansilla
Well put. It still puzzles me that promises and/or CPS don't have a greater
adoption in the JavaScript community. I guess that what happens is that the
concept of a callback is a very easy to understand one, but a system becomes
more complicated and cumbersome (exponentially, I would say) with every new
callback that is added to it. The real problem comes when creating big async
applications in JavaScript based entirely in callbacks, as it is the norm now
specially in NodeJS projects. Using callbacks to build complex applications is
a sure way to un-maintainability.

~~~
lobo_tuerto
I found this very useful for architecting larga javascript aps:
[http://speakerdeck.com/u/addyosmani/p/large-scale-
javascript...](http://speakerdeck.com/u/addyosmani/p/large-scale-javascript-
application-architecture)

------
stephank
It strikes me that this developer chooses to write an abstraction on top of JS
for solving his recurring problems, over simply using language features
readily available.

Promises are as much a pattern or mechanic as callbacks, but the latter feels
far more natural in JS. The `promised` decorator is interesting, but it has
problems:

\- The application I work on, and have in mind with this, would need just
about every function decorated.

\- It doesn't account for methods, unless you're default decorating the
method, ie.: `Foo.prototype.myMethod = promised(function(/* ... _/) { /_ ...
*/ });`

\- Every decorated function takes a noticable performance hit, because things
like `Function#apply` and concatenating `arguments` are relatively slow.

\- It doesn't sit well with me that the example rewrites a method on a
prototype declared elsewhere: `console.log = promised(console.log)`

Further, the article and library don't even scratch the surface of complicated
async flows. Think async versions of common functional-style methods like
`map`, `reduce`, etc.

For example, a basic scenario from our own build process is: Scan a directory
for template files, read them, compile them, then concatenate the result and
write it out.

We used to have a promise library to do all of this, from handling a build
process to performing database queries. I discovered Async.js at some point
and haven't look back since: <https://github.com/caolan/async>

~~~
MatthewPhillips
Promises are likely to be baked into JavaScript at some point in the
future[1], so I would recommend becoming familiar with them now. Even if you
don't use the pattern personally you will likely run into libraries that do
use it once it is part of the spec.

I don't too much like the promise pattern this article gives, Q is the
definitive implementation: <http://documentup.com/kriskowal/q/>

[1]<http://wiki.ecmascript.org/doku.php?id=strawman:concurrency>

~~~
gozala
Just to be clear this library implements just a subset of Q with exact same
API, with only addition of `promised` wrapper. I'm convinced that this wrapper
is a better way to deal with promises than dozens of utility functions that
you have to learn about.

For example Q.all is promised(Array) I find later more intuitive.

That's not to say don't use Q! Q is brilliant piece of software and I'd be
more than happy to see more people using it.

------
pestaa

        it’s possible to make sync function async
        it’s not the case other way round
    

Is this terminology correct? I thought it is easier to make async functions
sync by blocking it, and harder to unblock a sync one. Am I confusing this
with something else?

~~~
lucian1900
I think the OP refers to the syntax/API for each. If you're already using
async APIs, adding a sync one that runs in a separate thread won't change
much.

On the other hand, you need something like CPS or coroutines to cleanly use an
async function in a program mostly using sync APIs.

Of course, if you have the right tools (CPS/coroutines) you can make any async
API look sync, as you said.

~~~
gozala
I mainly was referring to JS where we don't have coroutines and there is no
plans to have them either.

------
wonnage
A good example of deferreds can be found in jQuery - every AJAX method returns
a deferred that you can chain success, error, etc. handlers to. So it's not
like this idea isn't a mainstream one.

The main problem I see is that very few libraries handle receiving promises as
arguments, probably because there isn't a standard/widely-used implementation
of them. So your logic ends up being backwards, e.g you'd chain
Mustache.render off of a jQuery success promise, rather than just passing the
success promise in.

~~~
gozala
What I'm suggesting is that promises don't need any special treatment. If you
have a function that you want to feed a promise just wrap it:
promised(Mustache.render). That's all it takes.

------
jahewson
The code doesn't actually work though, the very first example is broken:

    
    
        function sum(a, b) { return a + b }
        sum = promised(sum)
    
        var a = defer()         // make promise
        var b = sum(a, 1)
        var b = sum(b, 5)
        console.log(b)          // eventually prints => 17
        a.resolve(11)           // fulfill promise
    

Prints:

    
    
        [object Object]15

~~~
gozala
I have already fixed that, it was a typo, I meant following instead:

    
    
        var deferred = defer()          // make promise
        var a = deferred.promise
        var b = sum(a, 1)
        var c = sum(b, 5)
        console.log(c)                  // eventually prints => 17
        deferred.resolve(11)            // fulfill promise

~~~
ricardobeat
You were writing an article about it and didn't get it right on the first time
- maybe that's the reason more people don't use it.

~~~
skrebbel
That, or a majority of the JS coding crowd is too novice to appreciate
maintainable code better than copying and pasting "simple" plumbing all over
the place.

------
dreadpirateryan
For any node.js devs out there, here is the promises library I've been using
with great success: <https://github.com/coolaj86/futures/tree/v2.0/future>

------
lucian1900
This is one of the simplest implementations of deferreds I've seen in JS so
far.

~~~
drostie
It looks like a bunch of us have had the same idea for Node.js. I wrote for
example this: <https://github.com/drostie/ducky/blob/master/promises.js>

I've abandoned it at this point for a very particular reason: operators don't
work well in this phrasing. That is, the example case given in the above
discussion:

    
    
        function makeView(templateURI, dataURI) {
            var template = readURI(templateURI),
                data = readURI(dataURI);
            return Mustache.render(template, data);
        }
    

...while it's not bad, also doesn't actually try to "write logic", in a post
that's about "write logic, not mechanics."

What you really want to do is much more complicated because the example code
starts to look ugly:

    
    
        var userPromise = db.getUser(data.session);
        return userPromise.attr("role").equals("admin").then(
            render(open("yay.xml"), db.send(data.request)),
            render(open("no_permissions.xml"), {})
        );
    

Don't get me wrong, I still like the idea and think that there might be a very
promising way to do this sort of work in Node. Certainly I prefer those five
lines to always writing:

    
    
        db.getUser(data.session, function (err, user) {
            if (err) return callback(err);
            if (user.role === "admin") {
                db.send(data.request, function (err, reply) {
                    if (err) return callback(err);
                    render_file("yay.xml", reply, callback);
                });
            } else {
                render_file("no_permissions.xml", {}, callback);
            }
        });
    

But as much as I _really_ don't like that lame error stuff which breaks in a
stiff wind, I also _really_ want to be cautious about the exchange of these
two lines:

    
    
        if (user.role === "admin") {
        
        userPromise.attr("role").equals("admin").then(
    

What we really want, I guess, is some sort of mesoscopic system -- we still
want operators and familiar control structures from our "micro" world, but we
also want lazy evaluations and so on from our "macro" framework. This is not
impossible but it is hard to get right. If my "ducky" project moves forward it
will probably look something like this:

    
    
        return db.getUser(data.session)(function (user) {
            return (user.role === admin) ? 
                 render(open("yay.xml"), db.send(data.request)) :
                 render(open("no_permissions.xml"), {})
        });
    

You bubble up the lazy constructs with returns, the error handling gets
internalized within the lazy constructs, and the "control-method" invocation
allows you to build an arbitrary control structure with whatever object you
have right now.

------
EtienneK
The lack of semicolons in the article's examples makes me uneasy...

~~~
pygy_
_Oh noes!!! and his library starts with the dreaded exclamation point!!!_ \--
another disgruntled JavaScripter.

I know that people identify strongly with technical choices[0] (and if you
feel uneasy, you're probably the victim of this natural inclination of
ours[1]), but I'm tired of the semicolon drama here on HN.

Could we please stop?

\--

[0] <http://paulgraham.com/identity.html>

[1] or did I miss your sarcasm?

~~~
possibilistic
I detect sarcasm. Especially given the headlines of the past week.

Constructive post though, thanks!

------
ricardobeat
That last line

    
    
        return Mustache.render(template, data)
    

Isn't exactly equivalent to the non-promise one, since now `Mustache.render`
is async, is it?

~~~
wonnage
It's much more useful now, IMO. Now you can chain an error handler onto your
view's render method, and the level of abstraction becomes "I couldn't render
the view" rather than "I couldn't get some JSON from the server".

Functionally the behavior is the same - you're still going to have to gate an
asynchronous stream of actions (make sure steps a, b, c have completed before
d, etc.), but with this, you can describe that logic where it matters -
renderView().then(attachHandlers).then..., instead of callback nesting hell
(attachHandlers would have to be in renderView).

------
stcredzero
I will be down voted for saying so, but "than" and "then" seem to be reversed
throughout the entire article. I would like to learn more about promises now.

~~~
gozala
You're absolutely right! My English is far from being perfect and in addition
I was rushing to get this post out making bunch of mistakes. I tried to fix
all the "than" "then" issues, thanks for pointing that out ;)

~~~
stcredzero
I was thinking about promises, because I just wrote a procedurally generated
universe in Javascript with over 2^100 locations. To do the procedural
generation correctly, the Math.random() function has to be called in the same
order every time for generating each "sector." I had used promises in
Smalltalk, but never found an application super for them and was thinking that
promises would be a way to code this cleanly.

------
alexchamberlain
A very well thought out article.

