Execute Tasks in the Loop

Execute Tasks In the Loop Using Async.each

Now I am going to show you how to execute asynchronous Tasks In the Loop by using async.each

const Client = require('node-rest-client').Client;

const restClientService = new Client();

restClientService.registerMethod('getPosts', 'http://jsonplaceholder.typicode.com/users/1/posts', 'GET');

restClientService.registerMethod('getAlbums', 'http://jsonplaceholder.typicode.com/users/1/albums', 'GET');

restClientService.registerMethod('getPhotos', 'http://jsonplaceholder.typicode.com/albums/1/photos', 'GET');

export default restClientService;

 

function loopDemo(req, res, next) {
    let users = [1, 2, 3, 4, 5, 6];
    let results = [];

    async.each(users, (userId, cb) => {

        RestClientService
            .get(`http://jsonplaceholder.typicode.com/users/${userId}/posts`,
                (posts, response) => {
                    if (response.statusCode !== 200) {
                        return cb('Unable to fetch the posts');
                    }
                    results.push(posts);
                    return cb();
                });
    }, err => {
        if (err) {
            return res.status(500).send(err);
        }
        return res.json(results);
    })

Async.each always take an array of functions. The second argument will be iterator function. This iterator function run for every item of the collection. I have an array of userId. I want to get all the posts for six users. If you get an error and your response is not equal to 200. I am calling the callback with the error value. It is immediately returned and run the final callback method with an error value.

You can see that I am adding posts array to results collection. So, results array will have the six posts elements. Each item will be an array of posts. If you are using callbacks, then Async.each is the best method to run tasks in the loop.

Create Angular 4.3 Project Using Angular-cli

1) Create Angular Project

You can choose any name. I don’t need to install the dependency right now because I want to install Angular 4.3.0 version. Let me show you how can you install them. Open the project. I am going to use Visual Studio code.I have successfully opened the project in Visual Studio code.

Let me open the package.json. The angular-cli has installed 4.2.4 version. I am going to change manually the version 4.3.0. You have to replace 4.2.4 to 4.3.0 if you want to use HTTPClient you must install angular version 4.3.0.

2) Install Angular4.3

I would like to show you how to use interceptors in Angular. Now I am going to install the dependencies by using yarn install. You can also install dependency by using npm install. It is installing 4.3.0 version it will take some time to install the dependencies.

Summary

  • You have learned how to create Angular project using Angular-cli
  • I have also shown you how to replace the Angular4.2 to Angular4.3.0

Node.js : Execute Tasks In Parallel

Use Case

If you want to run multiple tasks and you don’t need to wait for the previous method, then you have to run the asynchronous function in parallel. In this post, I will show you how to execute asynchronous tasks in parallel by using callbacks, promises, and Async/Await.We will have three asynchronous functions. I’m going to use Jsonplaceholder API to send the network request.I will show you how to get all the Posts for a particular User. Each User has many Albums. I am going to show you how to get all the Albums for a specific User. Each Album has many Photos. I will fetch all the Photos for a particular User.

The main important point is that we have to run all three asynchronous tasks in parallel.

Execute Tasks In Parallel Using Async.parallel

Now I am going to show you how to execute tasks in parallel using Async.parallel method.

const Client = require('node-rest-client').Client;
const restClientService = new Client();

restClientService.registerMethod('getPosts','http://jsonplaceholder.typicode.com/users/1/posts','GET');
restClientService.registerMethod('getAlbums','http://jsonplaceholder.typicode.com/users/1/albums','GET');
restClientService.registerMethod('getPhotos','http://jsonplaceholder.typicode.com/albums/1/photos','GET');

export default restClientService;
function parallelDemo(req, res, next) {

    async.parallel({
        posts: cb => {

            RestClientService.methods.getPosts((posts, response) => {
                if (response.statusCode !== 200) {
                    return cb('Unable to process posts request');
                }
                return cb(null, posts);
            })

        },
        albums: cb => {
            RestClientService.methods.getAlbums((albums, response) => {
                if (response.statusCode !== 200) {
                    return cb('Unable to process album request');
                }
                return cb(null, albums);
            })
        },
        photos: cb => {

            RestClientService.methods.getPhotos((photos, response) => {
                if (response.statusCode !== 200) {
                    return cb('Unable to process photos request');
                }
                return cb(null, photos);
            })
        }
    }, (err, result) => {
        if (err) {
            return res.status(500).send(err);
        }
        return res.json(result);
    })
}

 

Each object property, posts, albums, and photos are the functions. Each function will accept the callback argument. If something went wrong in any posts, albums or photos method, you need to call the callback with an error value.If everything is right, you have to call the callback function with return cb(null, photos); null means there is no error occurred in this callback method. When all the tasks complete their execution, then async.parallel will call the final callback with the result of the array. The result array will have three properties posts, albums, and photos collection.

Execute Tasks In Parallel Using Promises

Now I am going to show you how to execute Asynchronous functions in parallel using Promise.all method.

//axios-api.service.js
const axios = require('axios');

export function getPosts() {
    return axios.get('http://jsonplaceholder.typicode.com/users/1/posts');
}

export function getAlbums() {
    return axios.get('http://jsonplaceholder.typicode.com/users/1/albums');
}

export function getPhotos() {
    return axios.get('http://jsonplaceholder.typicode.com/albums/1/photos');
}

getPosts() will fetch all the posts from the JsonPlaceHolder API and return the Promise. Similarly, getAlbums() and  getPhotos()will return the Promise. I will show you how to consume these promises in PromiseDemoController.

import {
    getPosts,
    getAlbums,
    getPhotos
} from '../helpers/axios-api.service';

function parallelDemo(req, res, next) {
    Promise.all([
            getPosts(),
            getAlbums(),
            getPhotos()
        ])
        .then(results => {
            let [posts, albums, photos] = results;
            return res.json({
                posts: posts.data,
                albums: albums.data,
                photos: photos.data
            });
        })
        .catch(err => {
            return res.status(500).send(err);
        })
}

Promise.all will take the collection of promises. I have passed the array of promises to Promise.all When all the promises will be resolved, then  method will be called with the array of resolved values. I have destructured the results array into posts, albums, and photos.

If any of the promises rejected, promise.all will call the catch method immediately. This catch method will send the error to the server with 500 status code.

Execute Tasks In Parallel Using Async/Await

You can also run Asynchronous functions in Parallel by using Async/Await.

function parallelDemo(req, res, next) {

    const processRequest = async () => {

        const [posts, albums, photos] = await Promise.all([
            getPosts(),
            getAlbums(),
            getPhotos()
        ]);

        return {
            posts: posts.data,
            albums: albums.data,
            photos: photos.data
        };

    };

    processRequest()
        .then(rsp => {
            return res.json(rsp);
        })
        .catch(err => {
            return res.stats(500).send(err);
        });
}

You can also apply await expression on Promise.all method.  processRequest is an asynchronous function. It always returns a Promise. I have already shown you how to consume a Promise.

Source Code

https://github.com/HaiderMalik12/Parallel-Tasks-Node

 

 

Execute Asynchronous Tasks in Series

What is Callback

A callback is an asynchronous equivalent for a function. A callback function is called at the completion of a given task.

function login(callback) {
    //do some operation 
    callback(‘You have successfully LoggedIn’);
}
login(function(result) {
    console.log(result);
});

 

I have created a login function. This login function is accepting one argument which is the callback. I am invoking the callback function after the completion of login method. It will immediately log the result to the console.

Use Case

I am going to show you how to implement this use case in node.js. How you can write clean code and execute asynchronous tasks in series.

What is CallbackHell

function seriesCallbackHell() {
    const company = new Company({
        name: 'FullStackHour'
    });
    company.save((err, savedCmp) => {
        if (err) {
            return next(err);
        }
        const job = new Job({
            title: 'Node.js Developer',
            _company: savedCmp._id
        });
        job.save((err, savedJob) => {
            if (err) {
                return next(err);
            }
            const application = new Application({
                _job: savedJob._id,
                _company: savedCmp._id
            });
            application.save((err, savedApp) => {
                if (err) {
                    return next(err);
                }
                const licence = new Licence({
                    name: 'FREE',
                    _application: savedApp._id
                });
                licence.save((err, savedLic) => {
                    if (err) {
                        return next(err);
                    }
                    return res.json({
                        company: savedCmp,
                        job: savedJob,
                        application: savedApp,
                        licence: savedLic
                    });
                });
            });
        });
    });
}

 

If there are heavily nested callbacks in your code, It will become a callback-hell. You can see that it’s tough to read and maintain the code. It’s complicated to debug. Now I am going to show you how to avoid callback-hell by using three design patterns in Node.js.

Execute Tasks In Series Using Async.series

First of all I am going to show you to execute asynchronous functions in series by using callbacks.If you want to use callbacks, you must use Async.js third party npm library.Now I need to use Async.series method.

function seriesDemo(req, res, next) {
    let rsp = {};
    const tasks = [function createCompany(cb) {
        const company = new Company({
            name: 'FullStackhour'
        });
        company.save(function(err, savedCompany) {
            if (err) {
                return cb(err);
            }
            rsp.company = savedCompany;
            return cb(null, savedCompany);
        });
    }, function createJob(cb) {
        const job = new Job({
            title: 'Node.js Developer',
            _company: rsp.company._id
        });
        job.save((err, savedJob) => {
            if (err) {
                return cb(err);
            }
            rsp.job = savedJob;
            return cb(null, savedJob);
        })
    }, function createApplication(cb) {
        const application = new Application({
            _job: rsp.job._id,
            _company: rsp.company._id
        });
        application.save((err, savedApp) => {
            if (err) {
                return cb(err);
            }
            rsp.application = savedApp;
            return cb(null, savedApp);
        })
    }, function createLicence(cb) {
        const licence = new Licence({
            name: 'FREE',
            _application: rsp.application._id
        });
        licence.save((err, savedLic) => {
            if (err) {
                return cb(err);
            }
            return cb(null, savedLic);
        })
    }];
    async.series(tasks, (err, results) => {
        if (err) {
            return next(err);
        }
        return res.json(results);
    })
}

 

Async.series takes the collection of asynchronous functions and optional callback method. When all the tasks complete the execution, then the final callback will be called and return the results to the server. This result variable will hold the array of the item with the company, job, application, and licence object.If something went wrong in any function, then it will immediately call the final callback function with error value and the rest of the methods will not run.

Execute Tasks In Series Using Async.waterfall

If your asynchronous tasks are dependent on each other or the next function needs to use the result of the previous method, then you have to use the async.waterfall approach. The significant difference between waterfall and series is that waterfall allows you to send the result to the next callback. Let me show you the example of Async.waterfall.

function waterfallDemo(req, res, next) {
    const tasks = [function createCompany(cb) {
        const company = new Company({
            name: 'FullStackhour'
        });
        company.save(function(err, savedCompany) {
            if (err) {
                return cb(err);
            }
            return cb(null, savedCompany);
        });
    }, function createJob(company, cb) {
        const job = new Job({
            title: 'Node.js Developer',
            _company: company._id
        });
        job.save((err, savedJob) => {
            if (err) {
                return cb(err);
            }
            return cb(null, {
                job: savedJob,
                company
            });
        });
    }, function createApplication(result, cb) {
        const application = new Application({
            _job: result.job._id,
            _company: result.company._id
        });
        application.save((err, savedApp) => {
            if (err) {
                return cb(err);
            }
            return cb(null, {
                job: result.job,
                company: result.company,
                application: savedApp
            });
        })
    }, function createLicence(result, cb) {
        const licence = new Licence({
            name: 'FREE',
            _application: result.application._id
        });
        licence.save((err, savedLic) => {
            if (err) {
                return cb(err);
            }
            return cb(null, {
                job: result.job,
                company: result.company,
                application: result.application,
                licence: savedLic
            });
        })
    }];
    async.waterfall(tasks, (err, results) => {
        if (err) {
            return next(err);
        }
        return res.json(results);
    })
}

 

You can see that createJob(company, cb) is dependent on the createCompany(cb)CreateJob function needs the id of the Company to save the job. Similarly, createApplication(result,cb) is reliant on the createJob task. In this way, you can run tasks in series and send the result to the next callback by using Async.waterfall.

What is  a promise

A Promise is an Object that may produce single value sometimes in the future either a resolved or a reason that is not resolved.Imagine that your friend is going to commit you he/she will go for a movie with you next week. A Promise has three states.

Pending

You don’t your friend will go to a movie with you or not.

Resolved

If promise has been resolved it means your friend is ready to watch a movie with you.

Rejected

If Promise has rejected he/she will not happy to go to a movie with you.Maybe your friend is busy with other activities.

const isFriendReady = true;
// Promise
const watchMovie = new Promise((resolve, reject) => {
    if (isFriendReady) {
        return resolve('You are going to watch a Fast Furious 8');
    } else {
        var reason = new Error('Your friend is not Ready');
        return reject(reason);
    }
});
// call our promise
const askFriend = () => {
    watchMovie
        .then((fulfilled) => {
            // Great!,You are going to watch a movie with your friend
            console.log(fulfilled);
        })
        .catch(error => {
            // ops, you're friend is not ready 😮
            console.log(error.message);
        });
}
askFriend();

 

I have created a watchMovie Promise. Promise always accepts executor function as an argument. In this executor function, you have to pass the resolve and reject. The resolve and reject both are functions. If Promise completes or executes successfully then, resolve function will be called with resolve valueIf Promise is not completed successfully, it will call the reject method.

I am consuming a Promise in askFreind method. If Promise has resolved successfully then method will be called with You are going to watch a Fast Furious 8

If Promise rejected, catch method will be called with this reason Your friend is not Ready

Execute Tasks In Series Using promise.chaining

const promiseChaining = (req, res, next) => {
    let rsp = {};
    const company = new Company({
        name: 'FullStackhour'
    });
    company.save().then(savedCompany => {
        rsp.company = savedCompany;
        const job = new Job({
            title: 'Node.js Developer',
            _company: rsp.company._id
        });
        return job.save();
    }).then(savedJob => {
        const application = new Application({
            _job: savedJob._id,
            _company: rsp.company._id
        });
        rsp.job = savedJob;
        return application.save();
    }).then(savedApp => {
        const licence = new Licence({
            name: 'FREE',
            _application: savedApp._id
        });
        rsp.application = savedApp;
        return licence.save();
    }).then(savedLic => {
        rsp.licence = savedLic;
        return res.json(rsp);
    }).catch(err => {
        return next(err);
    })
}

 

If you want to run tasks in series. You can use Promises Chaining. First of all it will create a new record in company model. The result will be returned to the next then method. Then method always returns a promise. When this promise will be resolved the result will catch in the next then chaining method.

If something went wrong in any method, catch method immediately called with the error value.

What is Async/Await

Async await has been introduced in node version 7.8. Some developers are using node version 6 or version 5. You can still use async await but you have to install the package async/await. I am using node version 7.8

let isFriendReady = true;
const watchMovie = new Promise((resolve, reject) => {
    if (isFriendReady) {
        return resolve('You are going to watch a Fast Furious 8');
    } else {
        var reason = new Error('Your friend is not Ready');
        return reject(reason);
    }
});
const askFriend = async () => {
    const result = await watchMovie;
    return result;
}
askFriend().then(result => {
    console.log(result);
}).catch(err => {
    console.error(err);
})

 

First of all, you need to create a new asynchronous function.We have created an asynchronous method with this async keyword it means now you can use await expression in this function. You can apply await expression on promises. Now we have only one promise watchMovie, apply await expression to watchMovie. The await operator is used to wait for the promise.

This await operator returns the resolved value of the promise and await expression causes the function execution to wait for the promise resolution and to resume the async function execution.When the promise has been resolved and this resolved value saves to result variable. I am also returning the result from the askFriend method.

Async function always returns a promise. You know how to consume a promise. When askFriend promise has been resolved then the method will be called with result value.

Execute Tasks In Series Using Async/Await

function seriesDemo(req, res, next) {
    const saveRequest = async () => {
        const company = new Company({
            name: 'FullStackhour'
        });
        const savedCompany = await company.save();
        const job = new Job({
            title: 'Node.js Developer',
            _company: savedCompany._id
        });
        const savedJob = await job.save();
        const application = new Application({
            _job: savedJob._id,
            _company: savedCompany._id
        });
        const savedApp = await application.save();
        const licence = new Licence({
            name: 'FREE',
            _application: savedApp._id
        });
        const savedLic = await licence.save();
        return {
            company: savedCompany,
            job: savedJob,
            application: savedApp,
            savedLic: licence
        };
    }
    saveRequest().then(result => {
        return res.json(result);
    }).catch(err => next(err));
}

 

Async/Await is one of the best ways to write Asynchronous code in Node.js. You can see that code looks very concise and clean. You can read, maintain and debug the code very easily. I highly recommend you to run functions in series by using Async/Await.

Source Code

https://github.com/HaiderMalik12/series_tasks_node