

Avoiding Nested Callbacks in JavaScript - panthomakos
http://ablogaboutcode.com/2011/06/30/avoiding-nested-callbacks-in-javascript

======
tlrobinson
These aren't very good examples. You shouldn't break up small pieces of code
just to avoid nested callbacks.

 _"Well, until you have two or three callbacks that respond differently to
fs.readFile and you start running out of function names, right?"_

That's a red flag right there. If you can't figure out a unique name for the
callback, perhaps it's not worth naming it.

If you have a reusable piece of code, or it's just getting unwieldy (~3 levels
deep or so), then you should consider breaking it out into it's own function.
But otherwise for simple things I think it's more readable to have it inline.

It's unfortunate JavaScript's anonymous function syntax is so verbose. It
would be much more pleasant with lightweight syntax (CoffeeScript, perhaps?)

~~~
starwed
The currently being worked on future version of javascript will have less
verbose syntax. Brendan Eich has blogged[1] about his proposals.

Instead of

    
    
      (function(x) { return x * x })

you could just write

    
    
      #(x) { x * x }.
    

[1]<http://brendaneich.com/2011/01/harmony-of-my-dreams/>

~~~
nxn
I thought the # shorthand for functions proposal was rejected?

~~~
jashkenas
It was indeed. None of the function shorthands made it into ES.next, but the
current leading contenders are:
[http://wiki.ecmascript.org/doku.php?id=strawman:arrow_functi...](http://wiki.ecmascript.org/doku.php?id=strawman:arrow_function_syntax)

    
    
        (x) -> x * x
    

And
[http://wiki.ecmascript.org/doku.php?id=strawman:block_lambda...](http://wiki.ecmascript.org/doku.php?id=strawman:block_lambda_revival)

    
    
        {|x| x * x}

------
zbanks
It's still nesting callbacks, just not inline.

Also, for the second example, this might be a cleaner solution:

    
    
        var fs = require('fs');
    
        function writeFile(filename){
          return function(err){
            if (err) throw err;
            console.log('Wrote ' + filename);
          }
        }
    
        function writeHello(){
          return fs.writeFile('./hello.txt', 'Hello!', writeFile("hello.txt"));
        }
    
        function writeWorld(){
          return fs.writeFile('./world.txt', 'World!', writeFile("world.txt"));
        }
    
        writeHello();
        writeWorld();

~~~
panthomakos
Absolutely - the code can be re-factored - but your example doesn't
demonstrate that you can used named functions/callbacks within closures to
further organize code.

------
reaktivo
Wouldn't this have a performance issue since the nested function is being
redeclared every time the outer function is called?

~~~
tlrobinson
It's certainly no worse than the first example with the anonymous functions
inline. But yes, worse than the second example, since it's creating closures
on each invocation.

~~~
panthomakos
The closures aren't meant to be more performant, they simply allow you to
separate your code. It's not fair to compare the unnamed function example with
the closure example, since the first doesn't create closures. If it did -
which would be necessary to create both functions - the examples would be
equally performant.

~~~
tlrobinson
The first and third examples are both creating closures. It doesn't matter if
they're named or not. Any time you see the "function" keyword within another
function, that's a closure.

Check out the performance of these three styles. #1 and #3 are almost
identical, #2 is significantly faster: <http://jsperf.com/closures-perf>

~~~
panthomakos
You make a good point and thanks for the performance link. I should have been
more clear. The first and third examples are only comprable in the way they
create closures - which is equivalent, but they are meant to demonstrate
different things. The first demonstrates nested callbacks while the last
example demonstrates named functions that are organized by closures.

------
praeclarum
Why?

"You should donate all your money to praeclarum." "Why?" "Because I said so."

~~~
DTrejo
Please elaborate on your question.

~~~
praeclarum
My reading of the title followed the first commenter.

For years we've been begging for locally bound function declarations so we
don't have to explicitly pass variables to callbacks and so we don't pollute
the global namespace with worker function names.

This article then proceeds to throw all that away so we can have named
functions. Worse, you can have names and locality that he ignores:

    
    
        function bigGuy() {
            function littleWorker() { /* stuff */ }
            begin(littleWorker);
        }
    

So my question, why do this? What are the benefits?

------
schleyfox
Is this not an obvious effect of first class functions? Was it necessary to
rename "functions" to "named callbacks"? Can't you do basically exactly this
with function pointers in C?

Hopefully v8 will implement some of the things from Mozilla's Javascript 1.8
like generators, which will make evented programming more interesting.

