Node JS Async Module Example

Async module is a third party Node JS module which can make a collection of javascript function executed by control. This article will tell you how to install async module and how to use it’s various methods to control your Node JS application’s work flow.

1. Install Async Module From NPM Repository.

  1. First execute command npm search async in terminal to search the module list.
  2. Then execute below command to install node async module globally.
    192:~ zhaosong$ sudo npm install async -g
    
    Password:
    
    + [email protected]
    
    added 2 packages in 3.422s
  3. After that you can see node module async has been installed in directory /usr/local/lib/node_modules/async.

2.Async Methods Introduction.

Usually the async methods is divided into three categories.

  1. Collections control methods.
  2. Execute flow control methods.
  3. Utils methods.

2.1 Collections Control Methods.

2.1.1 async.each(collection, iterate function, callback)

This method will execute the iterate function for each item of the collection object concurrently ( at same time ). Execute below example code.

// Include async module by absolute module install path.
var async = require('/usr/local/lib/node_modules/async');

var task_arr = [{name:'task_1', delay:500},{name:'task_2', delay:300},{name:'task_3', delay:200},];

/* async.each will execute the task in task array concurrently. */
async.each(task_arr, function(task, callback){

        console.log("Execute task : " + task.name);

        setTimeout(function(){
            console.log("Task timeout : " + task.name);
            /* Must invoke the callback function. */ 
            callback(null, task.name);
        }, task.delay);

    },function(error){
        if(error==undefined)
        {
            console.log("No error.");
        }else
        {
            console.log("The error message is " + error);
        }

    });

Above example code output is as below. Because task_1’s delay time is the longest, so it’s timeout message will be printed at last.

Execute task : task_1
Execute task : task_2
Execute task : task_3
Task timeout : task_3
Task timeout : task_2
Task timeout : task_1
No error.
2.1.2 async.eachSeries(collection, iterate function, callback)

This method will execute iterate function for each item in the collections by order ( one by one ).

// Include async module by absolute module install path.
var async = require('/usr/local/lib/node_modules/async');

var task_arr = [{name:'task_1', delay:500},{name:'task_2', delay:300},{name:'task_3', delay:200},];

// Execute every task in task array by order (one by one).
async.eachSeries(task_arr, function(task, callback){

    console.log("Execute task : " + task.name);

    setTimeout(function(){
        console.log("Task timeout : " + task.name);
        // Must invoke the callback function, otherwise this function will be executed only with the first item in collection.
        callback(null, task.name);
    }, task.delay);

},function(error){
    console.log(error);
});

Output is.

Execute task : task_1
Task timeout : task_1
Execute task : task_2
Task timeout : task_2
Execute task : task_3
Task timeout : task_3
null
2.1.3 async.eachLimit(collection, limit, iterate function, callback)

This method will execute iterate function for limit number of items in the collection concurrently. When one of the item execution complete, other not executed item will execute at once.

// Include async module by absolute module install path.
var async = require('/usr/local/lib/node_modules/async');

var task_arr = [{name:'task_1', delay:500},{name:'task_2', delay:400},{name:'task_3', delay:200},{name:'task_4', delay:300},{name:'task_5', delay:200}];

/* Execute task concurrently with limit numbers. For example below code will execute 3 task (task_1, task_2, task_3) concurrently at first.
   When one task (task_3 ) execute complete, another task( task_4 ) will be executed at once.*/
async.eachLimit(task_arr, 3, function(task, callback){

    console.log("Execute task : " + task.name);

    setTimeout(function(){
        console.log("Task timeout : " + task.name);
        // Must invoke the callback function, otherwise this function will be executed only with the first item in collection.
        callback(null, task.name);
    }, task.delay);

},function(error){
    console.log(error);
});

Below is output.

Execute task : task_1
Execute task : task_2
Execute task : task_3
Task timeout : task_3
Execute task : task_4
Task timeout : task_2
Execute task : task_5
Task timeout : task_1
Task timeout : task_4
Task timeout : task_5
null

2.2 Execution Flow Control Methods.

2.2.1 async.series(function_array, function(error, results)

This method can be used in scenario such as send email after save user data into database etc.

Execute the function in the array by order. In below example code, because function_3 pass an error message in the callback method, so function_4 and function_5 will not execute.

// Include async module by absolute module install path.
var async = require('/usr/local/lib/node_modules/async');

var function_1 = function (call_back_function) {

    console.log("Function_1 execute.");

    call_back_function(null, "function_1");
}

var function_2 = function (call_back_function) {

    console.log("Function_2 execute.");

    call_back_function(null, "function_2");
}

var function_3 = function (call_back_function) {

    console.log("Function_3 execute.");

    call_back_function("error in function_3", "function_3");
}

var function_4 = function (call_back_function) {

    console.log("Function_4 execute.");

    call_back_function(null, "function_4");
}

var function_5 = function (call_back_function) {

    console.log("Function_5 execute.");

    call_back_function(null, "function_5");
}

var function_array = [function_1, function_2, function_3, function_4, function_5];

async.series(function_array, function(error, results){
    console.log("Async series method.");

    console.log(results);

    if(error)
    {
        console.log(error);
    }
});

Output of above js code.

Function_1 execute.
Function_2 execute.
Function_3 execute.
Async series method.
[ 'function_1', 'function_2', 'function_3' ]
error in function_3
2.2.2 async.waterfall(tasks, callback)

This method will execute each task in tasks array by order, and previous executed task’s callback method’s second parameter will be passed to next task as first parameter.

// Include async module by absolute module install path.
var async = require('/usr/local/lib/node_modules/async');

async.waterfall([
    function(callback) {
        // 1 will be passed to second function as first parameter. 
        callback(null, 1);
    },
    function(function_one_arg, callback) {
        console.log("function_one_arg : " + function_one_arg);
        callback(null, function_one_arg * 2);
    },
    function(function_two_arg, callback) {
        console.log("function_two_arg : " + function_two_arg);
        callback(null, function_two_arg * 2);
    },
    function(function_three_arg, callback) {
        console.log("function_three_arg : " + function_three_arg);
        callback(null, function_three_arg * 2);
    }
], function(error, result) {
    console.log('error: ' + error);
    console.log('result: ' + result);
});

Above example output is.

function_one_arg : 1
function_two_arg : 2
function_three_arg : 4
error: null
result: 8
2.2.3 async.parallel(tasks, callback)

Parallel execute of multiple functions, each function is executed immediately, without waiting for other functions to execute first. But the data in the array passed to the final callback is in the order declared in tasks, rather than in the order of execution.

If a function fails, it immediately transfers the error and the result of the functions that has been executed to the parallel’s final callback. The value of other functions that are not executed will not be transmitted to the final data, but occupy a position.

// Include async module by absolute module install path.
var async = require('/usr/local/lib/node_modules/async');

async.parallel([
    function(callback) {
        console.log("Function one execute");
        setTimeout(function(){
            console.log("Function one timeout.")
            callback('', 'Function one');
        }, 300);
    },
    function(callback) {
        console.log("Function two execute");
        setTimeout(function(){
            console.log("Function two timeout.")
            callback('', 'Function two');
        }, 200);
    },
    function(callback) {
        console.log("Function three execute");
        setTimeout(function(){
            console.log("Function three timeout.")
            callback('', 'Function three');
        }, 100);
    }
], function(error, result) {
    console.log('error: ' + error);
    console.log('result: ' + result);
});

Below is code output。

Function one execute
Function two execute
Function three execute
Function three timeout.
Function two timeout.
Function one timeout.
error: null
result: Function one,Function two,Function three
2.2.4 async.auto(tasks, [callback])

Async auto method will control the code execute flow automatically by your configuration. Independent tasks can run in parallel, and dependent tasks can execute with specified order.

Below example will divide create file /tmp/test/example.txt process into four steps. Step1 and step2 has no dependent so they can run in parallel. Step3 will wait for step1 and step2 to complete and step4 will wait for step3 to complete.

  1. Retrieve example file data.
  2. Create example file folder.
  3. Create and write example file.
  4. Email the created example file.
// Include async module by absolute module install path.
var async = require('/usr/local/lib/node_modules/async');
// Require fs module to operate file.
var file_system = require('fs');

async.auto({
    // retrieveData and createFolder will execute in parallel.
    retrieveData: function (callback) {
        console.log("Start retrieve data.")
        setTimeout(function(){
            console.log('Retrieve data timeout.');
            callback(null, 'This is the test file data.');
        }, 300);
    },
    createFolder: function (callback) {
        console.log("Start create folder.")
        setTimeout(function(){
            console.log('Create folder timeout.');
            var folder = '/tmp/test';

            if(!file_system.existsSync(folder))
            {
                file_system.mkdirSync(folder, 0744);

            }

            callback(null, folder);
        }, 200);
    },
    // writeToFile will be executed after retrieveData and createFolder execute.
    writeToFile: ['retrieveData', 'createFolder', function(results, callback) {
        console.log("Start write data to file.")
        setTimeout(function(){
            console.log('Write to file timeout.');

            var user_file_data = results.retrieveData;

            var user_file_folder = results.createFolder;

            var user_file_path = user_file_folder + '/example.txt';

            file_system.writeFile(user_file_path, user_file_data, function(err) {
                if(err) {
                    return console.log(err);
                }

                console.log("The file was saved!");

                callback(null, user_file_path);
            });
        }, 300);
    }],
    // emailFiles will execute after writToFile.
    emailFiles: ['writeToFile', function(results, callback) {
        console.log('Email files.');
        callback(null, {'file':results.writeToFile, 'email':'[email protected]'});
    }]
}, function(err, results) {
    // This callback function will be invoked at last.
    console.log('Error : ', err);
    console.log('Results : ', results);
});

Below is the code output. Because create folder will use less time than retrieve data, so create folder will complete first.

Start retrieve data.
Start create folder.
Create folder timeout.
Retrieve data timeout.
Start write data to file.
Write to file timeout.
The file was saved!
Email files.
Error : null
Results : { createFolder: '/tmp/test',
 retrieveData: 'This is the test file data.',
 writeToFile: '/tmp/test/example.txt',
 emailFiles: { file: '/tmp/test/example.txt', email: '[email protected]' } }

After run above example you can see the created file /tmp/test/example.txt with correct content.

Reference

  1. https://www.npmjs.com/package/async

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.