• United States+1
  • United Kingdom+44
  • Afghanistan (‫افغانستان‬‎)+93
  • Albania (Shqipëri)+355
  • Algeria (‫الجزائر‬‎)+213
  • American Samoa+1684
  • Andorra+376
  • Angola+244
  • Anguilla+1264
  • Antigua and Barbuda+1268
  • Argentina+54
  • Armenia (Հայաստան)+374
  • Aruba+297
  • Australia+61
  • Austria (Österreich)+43
  • Azerbaijan (Azərbaycan)+994
  • Bahamas+1242
  • Bahrain (‫البحرين‬‎)+973
  • Bangladesh (বাংলাদেশ)+880
  • Barbados+1246
  • Belarus (Беларусь)+375
  • Belgium (België)+32
  • Belize+501
  • Benin (Bénin)+229
  • Bermuda+1441
  • Bhutan (འབྲུག)+975
  • Bolivia+591
  • Bosnia and Herzegovina (Босна и Херцеговина)+387
  • Botswana+267
  • Brazil (Brasil)+55
  • British Indian Ocean Territory+246
  • British Virgin Islands+1284
  • Brunei+673
  • Bulgaria (България)+359
  • Burkina Faso+226
  • Burundi (Uburundi)+257
  • Cambodia (កម្ពុជា)+855
  • Cameroon (Cameroun)+237
  • Canada+1
  • Cape Verde (Kabu Verdi)+238
  • Caribbean Netherlands+599
  • Cayman Islands+1345
  • Central African Republic (République centrafricaine)+236
  • Chad (Tchad)+235
  • Chile+56
  • China (中国)+86
  • Christmas Island+61
  • Cocos (Keeling) Islands+61
  • Colombia+57
  • Comoros (‫جزر القمر‬‎)+269
  • Congo (DRC) (Jamhuri ya Kidemokrasia ya Kongo)+243
  • Congo (Republic) (Congo-Brazzaville)+242
  • Cook Islands+682
  • Costa Rica+506
  • Côte d’Ivoire+225
  • Croatia (Hrvatska)+385
  • Cuba+53
  • Curaçao+599
  • Cyprus (Κύπρος)+357
  • Czech Republic (Česká republika)+420
  • Denmark (Danmark)+45
  • Djibouti+253
  • Dominica+1767
  • Dominican Republic (República Dominicana)+1
  • Ecuador+593
  • Egypt (‫مصر‬‎)+20
  • El Salvador+503
  • Equatorial Guinea (Guinea Ecuatorial)+240
  • Eritrea+291
  • Estonia (Eesti)+372
  • Ethiopia+251
  • Falkland Islands (Islas Malvinas)+500
  • Faroe Islands (Føroyar)+298
  • Fiji+679
  • Finland (Suomi)+358
  • France+33
  • French Guiana (Guyane française)+594
  • French Polynesia (Polynésie française)+689
  • Gabon+241
  • Gambia+220
  • Georgia (საქართველო)+995
  • Germany (Deutschland)+49
  • Ghana (Gaana)+233
  • Gibraltar+350
  • Greece (Ελλάδα)+30
  • Greenland (Kalaallit Nunaat)+299
  • Grenada+1473
  • Guadeloupe+590
  • Guam+1671
  • Guatemala+502
  • Guernsey+44
  • Guinea (Guinée)+224
  • Guinea-Bissau (Guiné Bissau)+245
  • Guyana+592
  • Haiti+509
  • Honduras+504
  • Hong Kong (香港)+852
  • Hungary (Magyarország)+36
  • Iceland (Ísland)+354
  • India (भारत)+91
  • Indonesia+62
  • Iran (‫ایران‬‎)+98
  • Iraq (‫العراق‬‎)+964
  • Ireland+353
  • Isle of Man+44
  • Israel (‫ישראל‬‎)+972
  • Italy (Italia)+39
  • Jamaica+1876
  • Japan (日本)+81
  • Jersey+44
  • Jordan (‫الأردن‬‎)+962
  • Kazakhstan (Казахстан)+7
  • Kenya+254
  • Kiribati+686
  • Kosovo+383
  • Kuwait (‫الكويت‬‎)+965
  • Kyrgyzstan (Кыргызстан)+996
  • Laos (ລາວ)+856
  • Latvia (Latvija)+371
  • Lebanon (‫لبنان‬‎)+961
  • Lesotho+266
  • Liberia+231
  • Libya (‫ليبيا‬‎)+218
  • Liechtenstein+423
  • Lithuania (Lietuva)+370
  • Luxembourg+352
  • Macau (澳門)+853
  • Macedonia (FYROM) (Македонија)+389
  • Madagascar (Madagasikara)+261
  • Malawi+265
  • Malaysia+60
  • Maldives+960
  • Mali+223
  • Malta+356
  • Marshall Islands+692
  • Martinique+596
  • Mauritania (‫موريتانيا‬‎)+222
  • Mauritius (Moris)+230
  • Mayotte+262
  • Mexico (México)+52
  • Micronesia+691
  • Moldova (Republica Moldova)+373
  • Monaco+377
  • Mongolia (Монгол)+976
  • Montenegro (Crna Gora)+382
  • Montserrat+1664
  • Morocco (‫المغرب‬‎)+212
  • Mozambique (Moçambique)+258
  • Myanmar (Burma) (မြန်မာ)+95
  • Namibia (Namibië)+264
  • Nauru+674
  • Nepal (नेपाल)+977
  • Netherlands (Nederland)+31
  • New Caledonia (Nouvelle-Calédonie)+687
  • New Zealand+64
  • Nicaragua+505
  • Niger (Nijar)+227
  • Nigeria+234
  • Niue+683
  • Norfolk Island+672
  • North Korea (조선 민주주의 인민 공화국)+850
  • Northern Mariana Islands+1670
  • Norway (Norge)+47
  • Oman (‫عُمان‬‎)+968
  • Pakistan (‫پاکستان‬‎)+92
  • Palau+680
  • Palestine (‫فلسطين‬‎)+970
  • Panama (Panamá)+507
  • Papua New Guinea+675
  • Paraguay+595
  • Peru (Perú)+51
  • Philippines+63
  • Poland (Polska)+48
  • Portugal+351
  • Puerto Rico+1
  • Qatar (‫قطر‬‎)+974
  • Réunion (La Réunion)+262
  • Romania (România)+40
  • Russia (Россия)+7
  • Rwanda+250
  • Saint Barthélemy (Saint-Barthélemy)+590
  • Saint Helena+290
  • Saint Kitts and Nevis+1869
  • Saint Lucia+1758
  • Saint Martin (Saint-Martin (partie française))+590
  • Saint Pierre and Miquelon (Saint-Pierre-et-Miquelon)+508
  • Saint Vincent and the Grenadines+1784
  • Samoa+685
  • San Marino+378
  • São Tomé and Príncipe (São Tomé e Príncipe)+239
  • Saudi Arabia (‫المملكة العربية السعودية‬‎)+966
  • Senegal (Sénégal)+221
  • Serbia (Србија)+381
  • Seychelles+248
  • Sierra Leone+232
  • Singapore+65
  • Sint Maarten+1721
  • Slovakia (Slovensko)+421
  • Slovenia (Slovenija)+386
  • Solomon Islands+677
  • Somalia (Soomaaliya)+252
  • South Africa+27
  • South Korea (대한민국)+82
  • South Sudan (‫جنوب السودان‬‎)+211
  • Spain (España)+34
  • Sri Lanka (ශ්‍රී ලංකාව)+94
  • Sudan (‫السودان‬‎)+249
  • Suriname+597
  • Svalbard and Jan Mayen+47
  • Swaziland+268
  • Sweden (Sverige)+46
  • Switzerland (Schweiz)+41
  • Syria (‫سوريا‬‎)+963
  • Taiwan (台灣)+886
  • Tajikistan+992
  • Tanzania+255
  • Thailand (ไทย)+66
  • Timor-Leste+670
  • Togo+228
  • Tokelau+690
  • Tonga+676
  • Trinidad and Tobago+1868
  • Tunisia (‫تونس‬‎)+216
  • Turkey (Türkiye)+90
  • Turkmenistan+993
  • Turks and Caicos Islands+1649
  • Tuvalu+688
  • U.S. Virgin Islands+1340
  • Uganda+256
  • Ukraine (Україна)+380
  • United Arab Emirates (‫الإمارات العربية المتحدة‬‎)+971
  • United Kingdom+44
  • United States+1
  • Uruguay+598
  • Uzbekistan (Oʻzbekiston)+998
  • Vanuatu+678
  • Vatican City (Città del Vaticano)+39
  • Venezuela+58
  • Vietnam (Việt Nam)+84
  • Wallis and Futuna+681
  • Western Sahara (‫الصحراء الغربية‬‎)+212
  • Yemen (‫اليمن‬‎)+967
  • Zambia+260
  • Zimbabwe+263
  • Åland Islands+358
Thanks! We'll be in touch in the next 12 hours
Oops! Something went wrong while submitting the form.

Understanding Node.js Async Flows: Parallel, Serial, Waterfall and Queues

Nikita Sinha

Full-stack Development

Promises in Javascript has been around for a long time now. It helped solve the problem of callback hell. But as soon as the requirements get complicated with control flows, promises start getting unmanageable and harder to work with. This is where async flows come to the rescue. In this blog, let’s talk about the various async flows which are used frequently rather than raw promises and callbacks.

Async Utility Module

Async is a utility module which provides straight-forward, powerful functions for working with asynchronous JavaScript. Although it is built on top of promises, it makes asynchronous code look and behave a little more like synchronous code, making it easier to read and maintain.

Async utility has a number of control flows. Let’s discuss the most popular ones and their use cases:

1. Parallel

When we have to run multiple tasks independent of each other without waiting until the previous task has completed, parallel comes into the picture.

async.parallel(tasks, callback)
view raw parallel.js hosted with ❤ by GitHub

Tasks: A collection of functions to run. It can be an array, an object or any iterable.

Callback: This is the callback where all the task results are passed and is executed once all the task execution has completed.

In case an error is passed to a function's callback, the main callback is immediately called with the error. Although parallel is about starting I/O tasks in parallel, it’s not about parallel execution since Javascript is single-threaded.

An example of Parallel is shared below:

async.parallel([
function(callback) {
setTimeout(function() {
console.log('Task One');
callback(null, 1);
}, 200);
},
function(callback) {
setTimeout(function() {
console.log('Task Two');
callback(null, 2);
}, 100);
}
],
function(err, results) {
console.log(results);
// the results array will equal [1, 2] even though
// the second function had a shorter timeout.
});
// an example using an object instead of an array
async.parallel({
task1: function(callback) {
setTimeout(function() {
console.log('Task One');
callback(null, 1);
}, 200);
},
task2: function(callback) {
setTimeout(function() {
console.log('Task Two');
callback(null, 2);
}, 100);
}
}, function(err, results) {
console.log(results);
// results now equals to: { task1: 1, task2: 2 }
});

2. Series

When we have to run multiple tasks which depend on the output of the previous task, series comes to our rescue.

async.series(tasks, callback)
view raw series.js hosted with ❤ by GitHub

Tasks: A collection of functions to run. It can be an array, an object or any iterable.

Callback: This is the callback where all the task results are passed and is executed once all the task execution has completed.

Callback function receives an array of result objects when all the tasks have been completed. If an error is encountered in any of the task, no more functions are run but the final callback is called with the error value.

An example of Series is shared below:

async.series([
function(callback) {
console.log('one');
callback(null, 1);
},
function(callback) {
console.log('two');
callback(null, 2);
},
function(callback) {
console.log('three');
callback(null, 3);
}
],
function(err, results) {
console.log(result);
// results is now equal to [1, 2, 3]
});
async.series({
1: function(callback) {
setTimeout(function() {
console.log('Task 1');
callback(null, 'one');
}, 200);
},
2: function(callback) {
setTimeout(function() {
console.log('Task 2');
callback(null, 'two');
}, 300);
},
3: function(callback) {
setTimeout(function() {
console.log('Task 3');
callback(null, 'three');
}, 100);
}
},
function(err, results) {
console.log(results);
// results is now equal to: { 1: 'one', 2: 'two', 3:'three' }
});

3. Waterfall

When we have to run multiple tasks which depend on the output of previous task, Waterfall can be helpful.

async.waterfall(tasks, callback)
view raw waterfall.js hosted with ❤ by GitHub

Tasks: A collection of functions to run. It can be an array, an object or any iterable structure.

Callback: This is the callback where all the task results are passed and is executed once all the task execution has completed.

It will run one function at a time and pass the result of the previous function to the next one.

An example of Waterfall is shared below:

async.waterfall([
function(callback) {
callback(null, 'Task 1', 'Task 2');
},
function(arg1, arg2, callback) {
// arg1 now equals 'Task 1' and arg2 now equals 'Task 2'
let arg3 = arg1 + ' and ' + arg2;
callback(null, arg3);
},
function(arg1, callback) {
// arg1 now equals 'Task1 and Task2'
arg1 += ' completed';
callback(null, arg1);
}
], function(err, result) {
// result now equals to 'Task1 and Task2 completed'
console.log(result);
});
// Or, with named functions:
async.waterfall([
myFirstFunction,
mySecondFunction,
myLastFunction,
], function(err, result) {
// result now equals 'Task1 and Task2 completed'
console.log(result);
});
function myFirstFunction(callback) {
callback(null, 'Task 1', 'Task 2');
}
function mySecondFunction(arg1, arg2, callback) {
// arg1 now equals 'Task 1' and arg2 now equals 'Task 2'
let arg3 = arg1 + ' and ' + arg2;
callback(null, arg3);
}
function myLastFunction(arg1, callback) {
// arg1 now equals 'Task1 and Task2'
arg1 += ' completed';
callback(null, arg1);
}

4. Queue

When we need to run a set of tasks asynchronously, queue can be used. A queue object based on an asynchronous function can be created which is passed as worker.

async.queue(task, concurrency)
view raw queue.js hosted with ❤ by GitHub

Task: Here, it takes two parameters, first - the task to be performed and second - the callback function.

Concurrency: It is the number of functions to be run in parallel.

async.queue returns a queue object that supports few properties:

  • push: Adds tasks to the queue to be processed.
  • drain: The drain function is called after the last task of the queue.
  • unshift: Adds tasks in front of the queue.

An example of Queue is shared below:

// create a queue object with concurrency 2
var q = async.queue(function(task, callback) {
console.log('Hello ' + task.name);
callback();
}, 2);
// assign a callback
q.drain = function() {
console.log('All items have been processed');
};
// add some items to the queue
q.push({name: 'foo'}, function(err) {
console.log('Finished processing foo');
});
q.push({name: 'bar'}, function (err) {
console.log('Finished processing bar');
});
// add some items to the queue (batch-wise)
q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function(err) {
console.log('Finished processing item');
});
// add some items to the front of the queue
q.unshift({name: 'bar'}, function (err) {
console.log('Finished processing bar');
});

5. Priority Queue

It is the same as queue, the only difference being that a priority can be assigned to the tasks which is considered in ascending order.

async.priorityQueue(task,concurrency)

Task: Here, it takes three parameters:

  • First - task to be performed.
  • Second - priority, it is a number that determines the sequence of execution. For array of tasks, the priority remains same for all of them.
  • Third - Callback function.


The async.priorityQueue does not support ‘unshift property of the queue.

An example of Priority Queue is shared below:

// create a queue object with concurrency 1
var q = async.priorityQueue(function(task, callback) {
console.log('Hello ' + task.name);
callback();
}, 1);
// assign a callback
q.drain = function() {
console.log('All items have been processed');
};
// add some items to the queue with priority
q.push({name: 'foo'}, 3, function(err) {
console.log('Finished processing foo');
});
q.push({name: 'bar'}, 2, function (err) {
console.log('Finished processing bar');
});
// add some items to the queue (batch-wise) which will have same priority
q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], 1, function(err) {
console.log('Finished processing item');
});

6. Race

It runs all the tasks in parallel, but as soon as any of the function completes its execution or passes error to its callback, the main callback is immediately called.

async.race(tasks, callback)
view raw race.js hosted with ❤ by GitHub

Task: Here, it is a collection of functions to run. It is an array or any iterable.

Callback: The result of the first complete execution is passed. It may be the result or error.

An example of Race is shared below:

async.race([
function (callback) {
setTimeout(function () {
callback(null, 'one');
}, 300);
},
function (callback) {
setTimeout(function () {
callback(null, 'two');
}, 100);
},
function (callback) {
setTimeout(function () {
callback(null, 'three');
}, 200);
}
],
// main callback
function (err, result) {
// the result will be equal to 'two' as it finishes earlier than the other 2
console.log('The result is ', result);
});

Combining Async Flows

In complex scenarios, the async flows like parallel and series can be combined and nested. This helps in achieving the expected output with the benefits of async utilities.

However, the only difference between Waterfall and Series async utility is that the final callback in series receives an array of results of all the task whereas in Waterfall, the result object of the final task is received by the final callback.

Conclusion

Async Utilities has an upper hand over promises due to its concise and clean code, better error handling and easier debugging. It makes us realize how simple and easy asynchronous code can be without the syntactical mess of promises and callback hell.

Get the latest engineering blogs delivered straight to your inbox.
No spam. Only expert insights.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Did you like the blog? If yes, we're sure you'll also like to work with the people who write them - our best-in-class engineering team.

We're looking for talented developers who are passionate about new emerging technologies. If that's you, get in touch with us.

Explore current openings

Understanding Node.js Async Flows: Parallel, Serial, Waterfall and Queues

Promises in Javascript has been around for a long time now. It helped solve the problem of callback hell. But as soon as the requirements get complicated with control flows, promises start getting unmanageable and harder to work with. This is where async flows come to the rescue. In this blog, let’s talk about the various async flows which are used frequently rather than raw promises and callbacks.

Async Utility Module

Async is a utility module which provides straight-forward, powerful functions for working with asynchronous JavaScript. Although it is built on top of promises, it makes asynchronous code look and behave a little more like synchronous code, making it easier to read and maintain.

Async utility has a number of control flows. Let’s discuss the most popular ones and their use cases:

1. Parallel

When we have to run multiple tasks independent of each other without waiting until the previous task has completed, parallel comes into the picture.

async.parallel(tasks, callback)
view raw parallel.js hosted with ❤ by GitHub

Tasks: A collection of functions to run. It can be an array, an object or any iterable.

Callback: This is the callback where all the task results are passed and is executed once all the task execution has completed.

In case an error is passed to a function's callback, the main callback is immediately called with the error. Although parallel is about starting I/O tasks in parallel, it’s not about parallel execution since Javascript is single-threaded.

An example of Parallel is shared below:

async.parallel([
function(callback) {
setTimeout(function() {
console.log('Task One');
callback(null, 1);
}, 200);
},
function(callback) {
setTimeout(function() {
console.log('Task Two');
callback(null, 2);
}, 100);
}
],
function(err, results) {
console.log(results);
// the results array will equal [1, 2] even though
// the second function had a shorter timeout.
});
// an example using an object instead of an array
async.parallel({
task1: function(callback) {
setTimeout(function() {
console.log('Task One');
callback(null, 1);
}, 200);
},
task2: function(callback) {
setTimeout(function() {
console.log('Task Two');
callback(null, 2);
}, 100);
}
}, function(err, results) {
console.log(results);
// results now equals to: { task1: 1, task2: 2 }
});

2. Series

When we have to run multiple tasks which depend on the output of the previous task, series comes to our rescue.

async.series(tasks, callback)
view raw series.js hosted with ❤ by GitHub

Tasks: A collection of functions to run. It can be an array, an object or any iterable.

Callback: This is the callback where all the task results are passed and is executed once all the task execution has completed.

Callback function receives an array of result objects when all the tasks have been completed. If an error is encountered in any of the task, no more functions are run but the final callback is called with the error value.

An example of Series is shared below:

async.series([
function(callback) {
console.log('one');
callback(null, 1);
},
function(callback) {
console.log('two');
callback(null, 2);
},
function(callback) {
console.log('three');
callback(null, 3);
}
],
function(err, results) {
console.log(result);
// results is now equal to [1, 2, 3]
});
async.series({
1: function(callback) {
setTimeout(function() {
console.log('Task 1');
callback(null, 'one');
}, 200);
},
2: function(callback) {
setTimeout(function() {
console.log('Task 2');
callback(null, 'two');
}, 300);
},
3: function(callback) {
setTimeout(function() {
console.log('Task 3');
callback(null, 'three');
}, 100);
}
},
function(err, results) {
console.log(results);
// results is now equal to: { 1: 'one', 2: 'two', 3:'three' }
});

3. Waterfall

When we have to run multiple tasks which depend on the output of previous task, Waterfall can be helpful.

async.waterfall(tasks, callback)
view raw waterfall.js hosted with ❤ by GitHub

Tasks: A collection of functions to run. It can be an array, an object or any iterable structure.

Callback: This is the callback where all the task results are passed and is executed once all the task execution has completed.

It will run one function at a time and pass the result of the previous function to the next one.

An example of Waterfall is shared below:

async.waterfall([
function(callback) {
callback(null, 'Task 1', 'Task 2');
},
function(arg1, arg2, callback) {
// arg1 now equals 'Task 1' and arg2 now equals 'Task 2'
let arg3 = arg1 + ' and ' + arg2;
callback(null, arg3);
},
function(arg1, callback) {
// arg1 now equals 'Task1 and Task2'
arg1 += ' completed';
callback(null, arg1);
}
], function(err, result) {
// result now equals to 'Task1 and Task2 completed'
console.log(result);
});
// Or, with named functions:
async.waterfall([
myFirstFunction,
mySecondFunction,
myLastFunction,
], function(err, result) {
// result now equals 'Task1 and Task2 completed'
console.log(result);
});
function myFirstFunction(callback) {
callback(null, 'Task 1', 'Task 2');
}
function mySecondFunction(arg1, arg2, callback) {
// arg1 now equals 'Task 1' and arg2 now equals 'Task 2'
let arg3 = arg1 + ' and ' + arg2;
callback(null, arg3);
}
function myLastFunction(arg1, callback) {
// arg1 now equals 'Task1 and Task2'
arg1 += ' completed';
callback(null, arg1);
}

4. Queue

When we need to run a set of tasks asynchronously, queue can be used. A queue object based on an asynchronous function can be created which is passed as worker.

async.queue(task, concurrency)
view raw queue.js hosted with ❤ by GitHub

Task: Here, it takes two parameters, first - the task to be performed and second - the callback function.

Concurrency: It is the number of functions to be run in parallel.

async.queue returns a queue object that supports few properties:

  • push: Adds tasks to the queue to be processed.
  • drain: The drain function is called after the last task of the queue.
  • unshift: Adds tasks in front of the queue.

An example of Queue is shared below:

// create a queue object with concurrency 2
var q = async.queue(function(task, callback) {
console.log('Hello ' + task.name);
callback();
}, 2);
// assign a callback
q.drain = function() {
console.log('All items have been processed');
};
// add some items to the queue
q.push({name: 'foo'}, function(err) {
console.log('Finished processing foo');
});
q.push({name: 'bar'}, function (err) {
console.log('Finished processing bar');
});
// add some items to the queue (batch-wise)
q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function(err) {
console.log('Finished processing item');
});
// add some items to the front of the queue
q.unshift({name: 'bar'}, function (err) {
console.log('Finished processing bar');
});

5. Priority Queue

It is the same as queue, the only difference being that a priority can be assigned to the tasks which is considered in ascending order.

async.priorityQueue(task,concurrency)

Task: Here, it takes three parameters:

  • First - task to be performed.
  • Second - priority, it is a number that determines the sequence of execution. For array of tasks, the priority remains same for all of them.
  • Third - Callback function.


The async.priorityQueue does not support ‘unshift property of the queue.

An example of Priority Queue is shared below:

// create a queue object with concurrency 1
var q = async.priorityQueue(function(task, callback) {
console.log('Hello ' + task.name);
callback();
}, 1);
// assign a callback
q.drain = function() {
console.log('All items have been processed');
};
// add some items to the queue with priority
q.push({name: 'foo'}, 3, function(err) {
console.log('Finished processing foo');
});
q.push({name: 'bar'}, 2, function (err) {
console.log('Finished processing bar');
});
// add some items to the queue (batch-wise) which will have same priority
q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], 1, function(err) {
console.log('Finished processing item');
});

6. Race

It runs all the tasks in parallel, but as soon as any of the function completes its execution or passes error to its callback, the main callback is immediately called.

async.race(tasks, callback)
view raw race.js hosted with ❤ by GitHub

Task: Here, it is a collection of functions to run. It is an array or any iterable.

Callback: The result of the first complete execution is passed. It may be the result or error.

An example of Race is shared below:

async.race([
function (callback) {
setTimeout(function () {
callback(null, 'one');
}, 300);
},
function (callback) {
setTimeout(function () {
callback(null, 'two');
}, 100);
},
function (callback) {
setTimeout(function () {
callback(null, 'three');
}, 200);
}
],
// main callback
function (err, result) {
// the result will be equal to 'two' as it finishes earlier than the other 2
console.log('The result is ', result);
});

Combining Async Flows

In complex scenarios, the async flows like parallel and series can be combined and nested. This helps in achieving the expected output with the benefits of async utilities.

However, the only difference between Waterfall and Series async utility is that the final callback in series receives an array of results of all the task whereas in Waterfall, the result object of the final task is received by the final callback.

Conclusion

Async Utilities has an upper hand over promises due to its concise and clean code, better error handling and easier debugging. It makes us realize how simple and easy asynchronous code can be without the syntactical mess of promises and callback hell.

Did you like the blog? If yes, we're sure you'll also like to work with the people who write them - our best-in-class engineering team.

We're looking for talented developers who are passionate about new emerging technologies. If that's you, get in touch with us.

Explore current openings