Node.js : Execute Tasks In Parallel

October 11, 2017

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

 

 

About the author

Haider Malik

Click here to add a comment

Leave a comment: