SlideShare a Scribd company logo
Avoiding Callback Hell with
Async.js

C. Aaron Cois, Ph.D.

www.codehenge.net
Sup

www.codehenge.net

@aaroncois
github.com/cacois
So, JavaScript?
What’s cool?
• Robust event model
• Asynchronous programming
• Client-side and Server-side
What’s cool?
• Robust event model
• Asynchronous programming
• Client-side and Server-side
What can cause headaches?
Callbacks

JavaScript uses callback functions to
handle asynchronous control flow
Anatomy of a Callback
fs = require('fs');
fs.readFile('f1.txt','utf8',function(err,data){
if (err) {
return console.log(err);
}
console.log(data);
});
Anatomy of a Callback
fs = require('fs');
fs.readFile('f1.txt','utf8',function(err,data){
if (err) {
return console.log(err);
}
console.log(data);
});

Anonymous, inline callback
Anatomy of a Callback
fs = require('fs');
fs.readFile('f1.txt','utf8',
function(err,data){
if (err) {
return console.log(err);
}
console.log(data);
}
);

Equivalent
formatting
Callback Hell

When working with callbacks, nesting
can get quite out of hand…
Callback Hell
func1(param, function(err, res) {
func2(param, function(err, res) {
func3(param, function(err, res) {
func4(param, function(err, res) {
func5(param, function(err, res) {
func6(param, function(err, res) {
func7(param, function(err, res) {
func8(param, function(err, res) {
func9(param, function(err, res) {
// Do something…
});
});
});
});
});
});
});
});
});
Callback Hell
func1(param, function(err, res) {
func2(param, function(err, res) {
func3(param, function(err, res) {
func4(param, function(err, res) {
func5(param, function(err, res) {
func6(param, function(err, res) {
func7(param, function(err, res) {
func8(param, function(err, res) {
func9(param, function(err, res) {
// Do something…
});
});
});
});
});
});
});
});
});
Best case, this is linear
func1

func2

func3

...

func9
But it can branch
func1

func2

func2

func3

func3

func3

func3

...

...

...

...

func9

func9

func9

func9
But it can branch
…
func2(param, function(err, results) {
_.each(results, func3(param, function(err, res) {
func4(param, function(err, res) {
…
});
}
});
});

func1

func2

func2

func3

func3

func3

func3

...

...

...

...

func9

func9

func9

func9
Some specific challenges
• When branching, we can’t know the
order of these function calls
• If we want parallel execution, we have
to do some real gymnastics to get
return data back together
• Also, scoping becomes a challenge
A more ‘real’ example
var db = require('somedatabaseprovider');
//get recent posts
http.get('/recentposts', function(req, res) {
// open database connection
db.openConnection('host', creds,function(err, conn){
res.param['posts'].forEach(post) {
conn.query('select * from users where
id='+post['user'],function(err,users){
conn.close();
res.send(users[0]);
});
}
});
});
A more ‘real’ example
var db = require('somedatabaseprovider');
//get recent posts
http.get('/recentposts', function(req, res) {
// open database connection
db.openConnection('host', creds,function(err, conn){
res.param['posts'].forEach(post) {
conn.query('select * from users where
id='+post['user'],function(err,users){
conn.close();
res.send(users[0]);
});
}
});
});
Solutions
• You can make this easier to read by
separating anonymous functions
• Passing function references instead of
anonymous functions helps even more
Inline callback
fs = require('fs');
fs.readFile('f1.txt','utf8',function(err,data){
if (err) {
return console.log(err);
}
console.log(data);
});
Separate Callback
fs = require('fs');
callback = function(err,data){
if (err) {
return console.log(err);
}
console.log(data);
}
fs.readFile('f1.txt','utf8',callback);
Can turn this:
var db = require('somedatabaseprovider');

http.get('/recentposts', function(req, res){
db.openConnection('host', creds, function(err,
conn){
res.param['posts'].forEach(post) {
conn.query('select * from users where id=' +
post['user'],function(err,results){
conn.close();
res.send(results[0]);
});
}
});
});
…into this
var db = require('somedatabaseprovider');

http.get('/recentposts', afterRecentPosts);
function afterRecentPosts(req, res) {
db.openConnection('host', creds, function(err, conn) {
afterDBConnected(res, conn);
});
}
function afterDBConnected(err, conn) {
res.param['posts'].forEach(post) {
conn.query('select * from users where id='+post['user'],afterQuery);
}
}
function afterQuery(err, results) {
conn.close();
res.send(results[0]);
}
Good start!
• Callback function separation is a nice
aesthetic fix
• The code is more readable, and thus
more maintainable
• But it doesn’t improve your control flow
– Branching and parallel execution are still
problems
Enter Async.js
Async.js provides common patterns for
asyncronous code control flow
https://github.com/caolan/async
BONUS: Also provides some common
functional programming paradigms
Client or Server -side
My examples will mostly be Node.js
code, but Async.js can be used in both
client and server side code
Serial/Parallel Execution
Run functions in series…
Function
1

Function
2

Function
3

Function
4

Function
2

Function
3

Function
4

…or parallel
Function
1
Serial/Parallel Functions
async.parallel([
function(){ ... },
function(){ ... }
], callback);
async.series([
function(){ ... },
function(){ ... }
]);
Serial/Parallel Functions
async.parallel([
function(){ ... },
function(){ ... }
], callback);
async.series([
function(){ ... },
function(){ ... }
]);

Single Callback!
Waterfall Execution
Async also provides a flow for serial
execution, passing results to successive
functions

Function
1

args

args

args
Function
2

Function
3

Function
4
Waterfall
async.waterfall([
function(){ callback(arg1); },
function(arg1) {
callback(ar2,ar3)
},
function(arg1, arg2){
callback(“done”)
}
], function(err, results){
// results now equals “done”
});
Times
Times() offers a shortcut to iterating over
a function multiple times in parallel
async.times(5, function(n, next) {
createUser(n,function(err, user {
next(err, user);
})
}, function(err, users){
// „users‟ now contains 5 users
});
Let’s see some code…
Collection Management
Functional programming provides some
useful tools that are becoming
mainstream

Specifically, map, reduce, and filter
operations are now common in many
languages
Map
The Map operation calls a given
function on each item of a list
Map
async.map([„file1‟,„file2‟,„file3‟],
funct,
callback);
async.mapSeries([„file1‟,„file2‟],
funct,
callback);

async.mapLimit([„file1‟,„file2‟,„file3‟],
limit,
funct,
callback);
Reduce
The Reduce operation aggregates a list
of values into a single result, using a
specified aggregation function
Reduce

Initial result state

async.reduce([val1,val2,…],memo,
function(memo,item,cb){
// doStuff
});
async.reduceRight([val1,val2],memo,
function(memo,item,cb){
// doStuff
});
Filter
To minimize computational overhead,
it’s often helpful to filter data sets to only
operate on acceptable values

Async.js provides a Filter function to do
just this
Filter
async.filter([„file1‟,„file2‟,„file3‟],
fs.exists,
function(results){
// results is now an array
// of files that exist
});
In Summation
Async.js provides:
• Powerful asynchronous control flows
• Functional programming tools

Write clean code, live the dream.
Thanks!

Any questions?

@aaroncois

More Related Content

PDF
Callbacks and control flow in Node js
Thomas Roch
 
PDF
Callbacks, promises, generators - asynchronous javascript
Łukasz Kużyński
 
PDF
Asynchronous programming done right - Node.js
Piotr Pelczar
 
PPTX
Avoiding callback hell in Node js using promises
Ankit Agarwal
 
PDF
Understanding Asynchronous JavaScript
jnewmanux
 
PDF
Javascript Promises/Q Library
async_io
 
PPTX
Promises, Promises
Domenic Denicola
 
PPTX
The Promised Land (in Angular)
Domenic Denicola
 
Callbacks and control flow in Node js
Thomas Roch
 
Callbacks, promises, generators - asynchronous javascript
Łukasz Kużyński
 
Asynchronous programming done right - Node.js
Piotr Pelczar
 
Avoiding callback hell in Node js using promises
Ankit Agarwal
 
Understanding Asynchronous JavaScript
jnewmanux
 
Javascript Promises/Q Library
async_io
 
Promises, Promises
Domenic Denicola
 
The Promised Land (in Angular)
Domenic Denicola
 

What's hot (20)

PDF
$q and Promises in AngularJS
a_sharif
 
PDF
Promise pattern
Sebastiaan Deckers
 
PDF
JavaScript Promise
Joseph Chiang
 
PPTX
JavaScript Promises
L&T Technology Services Limited
 
PDF
Introduction to reactive programming & ReactiveCocoa
Florent Pillet
 
PDF
The evolution of asynchronous javascript
Alessandro Cinelli (cirpo)
 
PDF
Avoiding callback hell with promises
TorontoNodeJS
 
PDF
JavaScript Promises
Tomasz Bak
 
PDF
Getting Comfortable with JS Promises
Asa Kusuma
 
PDF
JavaScript Promises
Derek Willian Stavis
 
PDF
How to send gzipped requests with boto3
Luciano Mammino
 
PDF
JavaScript promise
eslam_me
 
PDF
Practical JavaScript Promises
Asa Kusuma
 
PDF
Node.js: Continuation-Local-Storage and the Magic of AsyncListener
Islam Sharabash
 
PDF
Asynchronous Programming FTW! 2 (with AnyEvent)
xSawyer
 
PDF
CLS & asyncListener: asynchronous observability for Node.js
Forrest Norvell
 
PDF
Serverless, The Middy Way - Workshop
Luciano Mammino
 
PDF
Introducing Middy, Node.js middleware engine for AWS Lambda (FrontConf Munich...
Luciano Mammino
 
PPTX
Java Script Promise
Alok Guha
 
PDF
Middy.js - A powerful Node.js middleware framework for your lambdas​
Luciano Mammino
 
$q and Promises in AngularJS
a_sharif
 
Promise pattern
Sebastiaan Deckers
 
JavaScript Promise
Joseph Chiang
 
JavaScript Promises
L&T Technology Services Limited
 
Introduction to reactive programming & ReactiveCocoa
Florent Pillet
 
The evolution of asynchronous javascript
Alessandro Cinelli (cirpo)
 
Avoiding callback hell with promises
TorontoNodeJS
 
JavaScript Promises
Tomasz Bak
 
Getting Comfortable with JS Promises
Asa Kusuma
 
JavaScript Promises
Derek Willian Stavis
 
How to send gzipped requests with boto3
Luciano Mammino
 
JavaScript promise
eslam_me
 
Practical JavaScript Promises
Asa Kusuma
 
Node.js: Continuation-Local-Storage and the Magic of AsyncListener
Islam Sharabash
 
Asynchronous Programming FTW! 2 (with AnyEvent)
xSawyer
 
CLS & asyncListener: asynchronous observability for Node.js
Forrest Norvell
 
Serverless, The Middy Way - Workshop
Luciano Mammino
 
Introducing Middy, Node.js middleware engine for AWS Lambda (FrontConf Munich...
Luciano Mammino
 
Java Script Promise
Alok Guha
 
Middy.js - A powerful Node.js middleware framework for your lambdas​
Luciano Mammino
 
Ad

Similar to Avoiding Callback Hell with Async.js (20)

PDF
Node js
LearningTech
 
PDF
Flow control in node.js
iamhjoo (송형주)
 
PPTX
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Domenic Denicola
 
KEY
Playing With Fire - An Introduction to Node.js
Mike Hagedorn
 
PPTX
node.js workshop- JavaScript Async
Qiong Wu
 
PPTX
Node.js Patterns for Discerning Developers
cacois
 
PDF
Event Driven Javascript
Federico Galassi
 
PDF
Event driven javascript
Francesca1980
 
PDF
Event driven javascript
Francesca1980
 
PDF
Asynchronous programming with java script and node.js
Timur Shemsedinov
 
PDF
All you need to know about Callbacks, Promises, Generators
Brainhub
 
PDF
The art of concurrent programming
Iskren Chernev
 
PDF
Kamil witecki asynchronous, yet readable, code
Kamil Witecki
 
ODP
Node js
hazzaz
 
KEY
Node.js - Best practices
Felix Geisendörfer
 
PPTX
Async discussion 9_29_15
Cheryl Yaeger
 
PDF
Douglas Crockford: Serversideness
WebExpo
 
KEY
node.js: Javascript's in your backend
David Padbury
 
PDF
FITC - Node.js 101
Rami Sayar
 
PDF
Intro to Asynchronous Javascript
Garrett Welson
 
Node js
LearningTech
 
Flow control in node.js
iamhjoo (송형주)
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Domenic Denicola
 
Playing With Fire - An Introduction to Node.js
Mike Hagedorn
 
node.js workshop- JavaScript Async
Qiong Wu
 
Node.js Patterns for Discerning Developers
cacois
 
Event Driven Javascript
Federico Galassi
 
Event driven javascript
Francesca1980
 
Event driven javascript
Francesca1980
 
Asynchronous programming with java script and node.js
Timur Shemsedinov
 
All you need to know about Callbacks, Promises, Generators
Brainhub
 
The art of concurrent programming
Iskren Chernev
 
Kamil witecki asynchronous, yet readable, code
Kamil Witecki
 
Node js
hazzaz
 
Node.js - Best practices
Felix Geisendörfer
 
Async discussion 9_29_15
Cheryl Yaeger
 
Douglas Crockford: Serversideness
WebExpo
 
node.js: Javascript's in your backend
David Padbury
 
FITC - Node.js 101
Rami Sayar
 
Intro to Asynchronous Javascript
Garrett Welson
 
Ad

More from cacois (6)

PPTX
Devopssecfail
cacois
 
PPTX
Machine Learning for Modern Developers
cacois
 
PPTX
Hadoop: The elephant in the room
cacois
 
PPTX
High-Volume Data Collection and Real Time Analytics Using Redis
cacois
 
PPTX
Automate your Development Environments with Vagrant
cacois
 
PPTX
Node.js: A Guided Tour
cacois
 
Devopssecfail
cacois
 
Machine Learning for Modern Developers
cacois
 
Hadoop: The elephant in the room
cacois
 
High-Volume Data Collection and Real Time Analytics Using Redis
cacois
 
Automate your Development Environments with Vagrant
cacois
 
Node.js: A Guided Tour
cacois
 

Recently uploaded (20)

DOCX
Maharashtra Election Result 2024: Trends Compared to 2019 and 2024
maharashtraelection6
 
PDF
Starlink Faces Rare Global Outage_ Musk Apologizes, SpaceX Vows Fixes.pdf
Enterprise Wired
 
PDF
Israel’s Zones of Denial: What is the country becoming?
LUMINATIVE MEDIA/PROJECT COUNSEL MEDIA GROUP
 
PDF
Starlink Suffers Major Global Outage Due to Internal Software Failure.pdf
New India Abroad
 
PDF
Minority-Caucus-PRESS-STATEMENT-HOKN.pdf
JeorgeWilsonKingson1
 
PDF
25072025_First India Newspaper Jaipur.pdf
FIRST INDIA
 
PPTX
EU adopts 18th Sanctions Package against Russia
RT Consulting Limited
 
PPTX
What is Philosophy? The Meaning and how it works.pptx
arculankrishellemae
 
PPTX
11HUMSS-LESSSONS-POLITICSGOVERNANCE.pptx
CarlVillanueva11
 
PDF
U.S. Lawmakers Urge Action on Indian Student Visa Delays.pdf
New India Abroad
 
PDF
January_onlinecopy_2025_compressed.pdf.municip
municipluseonline
 
PDF
29072025_First India Newspaper Jaipur.pdf
FIRST INDIA
 
PDF
Reporter Travel: Telling Stories from the Field – Powered by 5wh.com
5whnewsletter
 
PPTX
Bhalla announces opening of Hoboken Fall Arts & Music Festival.pptx
New India Abroad
 
PPTX
The Branches of Philosophy-Grade 12.pptx
arculankrishellemae
 
PPTX
Naija Blog - Naija News, Top Nigerian Stories
Naija Blog
 
PPTX
Final The-End-of-the-Cold-War-and-the-Emergence-of-a-Unipolar-World.pptx
DonKobong
 
PPTX
Chiang Rai Battles Severe Flooding Affecting Over 4,400 Households
hepburnindia
 
PDF
Thailand_Cambodia_Travel_Advisories_Blogs.pdf
bumppy48
 
PDF
ACFrOgB7qGIQ8bhzZH1Pzz4DLzOiKY24QMUch6D2DeHr9Wmm6Me1clS-AgTR6FhMOpbl2iwGlABTp...
nyaguthiikennedy40
 
Maharashtra Election Result 2024: Trends Compared to 2019 and 2024
maharashtraelection6
 
Starlink Faces Rare Global Outage_ Musk Apologizes, SpaceX Vows Fixes.pdf
Enterprise Wired
 
Israel’s Zones of Denial: What is the country becoming?
LUMINATIVE MEDIA/PROJECT COUNSEL MEDIA GROUP
 
Starlink Suffers Major Global Outage Due to Internal Software Failure.pdf
New India Abroad
 
Minority-Caucus-PRESS-STATEMENT-HOKN.pdf
JeorgeWilsonKingson1
 
25072025_First India Newspaper Jaipur.pdf
FIRST INDIA
 
EU adopts 18th Sanctions Package against Russia
RT Consulting Limited
 
What is Philosophy? The Meaning and how it works.pptx
arculankrishellemae
 
11HUMSS-LESSSONS-POLITICSGOVERNANCE.pptx
CarlVillanueva11
 
U.S. Lawmakers Urge Action on Indian Student Visa Delays.pdf
New India Abroad
 
January_onlinecopy_2025_compressed.pdf.municip
municipluseonline
 
29072025_First India Newspaper Jaipur.pdf
FIRST INDIA
 
Reporter Travel: Telling Stories from the Field – Powered by 5wh.com
5whnewsletter
 
Bhalla announces opening of Hoboken Fall Arts & Music Festival.pptx
New India Abroad
 
The Branches of Philosophy-Grade 12.pptx
arculankrishellemae
 
Naija Blog - Naija News, Top Nigerian Stories
Naija Blog
 
Final The-End-of-the-Cold-War-and-the-Emergence-of-a-Unipolar-World.pptx
DonKobong
 
Chiang Rai Battles Severe Flooding Affecting Over 4,400 Households
hepburnindia
 
Thailand_Cambodia_Travel_Advisories_Blogs.pdf
bumppy48
 
ACFrOgB7qGIQ8bhzZH1Pzz4DLzOiKY24QMUch6D2DeHr9Wmm6Me1clS-AgTR6FhMOpbl2iwGlABTp...
nyaguthiikennedy40
 

Avoiding Callback Hell with Async.js

Editor's Notes

  • #2: Welcome. I’m going to talk today about callback hell, a place well-traveled by experienced javascript developers, as well as some other common control flows and patterns that make javascript – less than comfortable sometimes. I’m going to focus on Async.js, a useful JavaScript library for managing complex control flows. Async also has a number of other handy tricks up its sleeve to make your life easier, and I’ll show you some of them.
  • #3: So hi. I’m Aaron. Here’s a few places you can contact me, should you want to ask any questions later, or troll my posts.
  • #4: So, JavaScript? You guys know it, right? A language we all know and love. Once relegated to small-scale browser scripting, but now exploding into use everywhere. Remember back when Java was supposed to be in everything from servers to toasters? I think javascript has taken up that mantle.
  • #5: So why do I like javascript so much? Well, it’s a really nice language. C-ish syntax, efficiency and flexibility in the object model. And once people started really working with javascript, they discovered that it actually has an excellent event model, which gave it some robust asynchronous programming capabilities. Now, asynchronous-focused programing languages are nothing new, as anyone who’s worked with actionscript can attest, but Javascript has a particularly nice model. Also, javascript is now both a client and server-side language, thank to…
  • #6: …node.js. In fact, the pre-existing event model was one of the reasons javascript was such a perfect fit for an asynchronous server-side framework like Node.
  • #7: So javascript’s great, we all know it, but let’s talk about the skeletons in the closet. Every language has things that can cause you pain, and javascript is no exception.
  • #8: Javascript handles its asynchronous control flow using callbacks. Callbacks, while useful, allow your code to jump to any other spot in the code instantly, upon completion of a function. Because of this, some have described callbacks at the modern-day GOTO statement – and hopefully we all remember why GOTO is evil. Impossible to trace code, difficult to read and understand – its a maintainability issue. This is actually a really big deal, because low readability and maintainability is what inhibits certain languages, frameworks, and syntax paradigms from enabling the creation of large, long-lasting code bases. We are starting to build huge, full stack stuff with javascript, which means we have to start being very cognizant of the fact that large potentially numbers of developers with varying levels of expertise and understanding will need to look at our code, modify and extend our code, and debug our code.
  • #9: So let’s take a look at a callback. Point of note, most of my examples are going to be written in node.js syntax, because I’m a node guy and its easier to demo, but async.js itself, though originally written for node.js, now works in both client and server side javascript. So here’s a standard callback. We call the readfile method, pass it some parameters (a file and a format), and then pass it a callback function.
  • #10: Standard javascript convention is to use inline, anonymous functions as callbacks, which is what we see here.
  • #11: Because this conventional syntax often causes some confusion, let’s pick it apart to make sure its completely clear. Here’s equivalent, if slightly less elegant, syntax, separating out the entire anonymous function declaration. So there it is.
  • #12: The problem comes in when you start nesting callbacks. As in, my callback from an asyncronous function calls another asynchronous funciton, which has its own callback. And on, and on…
  • #13: We in the biz’ call this callback hell. Because its scary. And painful.
  • #14: And has a devil.
  • #15: Now let’s visualize what’s going on here. When a function is called, it goes off into the asynchronous, background ether. And the rest of the file continues to execute. When the function finishes its asynchronous task, it calls the callback. This ends up looking something like this, except the functions aren’t calling each other directly. Regardless, in the best case scenario, we have a linear callback path. Function 1 finishes, calls function 2. function 2 finishes, calls function 3. etc. Now without the asynchronous component, we’d be all set. These functions would call each other in a cascading fashion. But alas, these callbacks are asynchronous.
  • #16: Which means they can _branch_
  • #17: If I loop over a collection in function 1, and call an asynchronous function for each of 2 elements, I get 2 calls to its callback, function 2. If in one instance of func 2, we iterate over another collection, we get three instances of function 3. And each of these branches instances calls the full chain of future callbacks. Starting to see how this can get really out of hand?
  • #18: So other than being able to draw a non-confusing diagram, what’s the problem with branching? First, we lose any control over the order of calls within our callback chain. It’s unlikely, but theoretically a single branch could play out all the way down before any other branch starts. We are getting parallel execution, for some definition of parallel, but each branch will end with its own piece of data as a result of the full execution chain. Since we don’t know the order of execution, its tricky to aggregate all of these final return data values without global variables. Further, understanding and managing scope within so many nested functions can become extremely difficult.
  • #19: Here’s a more realistic piece of pseudocode. This is a very simple piece of code. It makes an http request, gets a response containing a number of recent posts (let’s assume this query is going to a blogging app with an API), opens a connection to a database, extracts the id of the user who wrote the post, and queries information about that user from the database. Even in this basic functionality, we have accumulated three nested callbacks, three anonymous inline functions.
  • #20: Here’s our friend. We can already see the nesting begin, without too much complexity to the functionality of our code. Whathappens when we add error handling? More nesting, harder to read code. Code that’s becoming harder to maintain.
  • #21: The first step in improving understandability and readability is to separate out those anonymous functions. Instead of passing an entire anonymous function into our asynchronous method, I’d rather pass a reference to a function formally defined elsewhere.
  • #22: So let’s remove the inline callback…
  • #23: … and define it as an object. We can then pass it into the async method. This is much easier to read, which is good.
  • #25: Sure, a few more lines of code. But look how much better the organization is. Look how much easier it would be to come in and immediately understand this code.
  • #27: So let’s talk about a solution to our control flow problems. Async.js is a fantastic library created by Caolan McMahon. Async gives you easy to use tools for a number of common control flows to address the problems we’ve been talking about, and also gives you some advanced collection management tools in the form of common functional programming paradigms. Let’s take a look so you can see what I mean.
  • #29: The first set of tools async provides are control flows for serial and parallel execution of functions. In some cases, you will want to run a number of asynchronous functions in series (while still allowing other code to execute during async operations). In many other cases, you want to run all of your functions in parallel, but to aggregate results when all computations are complete, as we discussed earlier. Async gives you nice, lean syntax to implement both of these control flows:
  • #30: Like so. Just pass a list of functions into an async.parallel or async.series function, and async will execute them as you have requested. You can declare these functions as inline anonymous functions, or separate them into independent function objects as I showed you earlier, to make the control flow code very small and readable. But wait, there’s more!
  • #31: You don’t have to manage the callback data pipeline directly anymore! For parallel execution, I can pass in as many functions as I want, and a single callback for all of them. Async will aggregate all return values from each function together into a single collection, and call the universal control flow callback when all parallel executions have completed. All of your data, in one place, delivered to you when computation is complete, with no work on your part. If you have ever had to deal with a lot of parallel execution, this is seriously cool. Refactoringcontrol flows is now much easier as well – you can see the small change to go from series to parallel. Just change the async method, and remove or add a callback. Two lines of code to change your entire execution strategy. This can be very powerful when you have complex systems and interactions.
  • #32: The one drawback to serial execution is that while async executes each function, one after the other, the functions have no way of talking to each other.