Avoiding Nested Callbacks in JavaScript
ablogaboutcode.com
ablogaboutcode.com
"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?)
Like what pg said somewhere (forgot where), having anonymous functions is a red flag in the language, because there shouldn't be any distinction between anonymous functions and named functions. Javascript kind of gets this right.
I believe CoffeeScript gets this even more right, by having a single way to declare functions which is also concise?
Instead of
(function(x) { return x * x })
you could just write #(x) { x * x }.
[1]http://brendaneich.com/2011/01/harmony-of-my-dreams/ (x) -> x * x
And http://wiki.ecmascript.org/doku.php?id=strawman:block_lambda... {|x| x * x} (x) { x * x }
[1] http://weepy.github.com/kaffeine/docs/function_extensions.ht... fs = require 'fs'
fs.mkdir './hello', 0777, ->
fs.writeFile './hello/world.txt', 'Hello!', ->
console.log 'File created with contents: '
fs.readFile './hello/world.txt', 'UTF-8', (err, data) ->
console.log dataAlso, 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();Check out the performance of these three styles. #1 and #3 are almost identical, #2 is significantly faster: http://jsperf.com/closures-perf
EDIT: took out function hoisting stuff, it doesn't get hoisted after a quick check.
"You should donate all your money to praeclarum." "Why?" "Because I said so."
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?"[Here's an example of] Avoiding Nested Callbacks"
instead of
"Avoiding Nested Callbacks [is important and something you should do]"
Hopefully v8 will implement some of the things from Mozilla's Javascript 1.8 like generators, which will make evented programming more interesting.