Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sequential execution of Promise.all

Hi I need to execute promises one after the other how do I achieve this using promise.all any help would be awesome. Below is the sample of my code I am currently using but it executes parallel so the search will not work properly

public testData: any = (req, res) => {
    // This method is called first via API and then promise is triggerd 
    var body = req.body;

    // set up data eg 2 is repeated twice so insert 2, 5 only once into DB
    // Assuming we cant control the data and also maybe 3 maybe inside the DB
    let arrayOfData = [1,2,3,2,4,5,5];

    const promises = arrayOfData.map(this.searchAndInsert.bind(this));

    Promise.all(promises)
        .then((results) => {
            // we only get here if ALL promises fulfill
            console.log('Success', results);
            res.status(200).json({ "status": 1, "message": "Success data" });
        })
        .catch((err) => {
            // Will catch failure of first failed promise
            console.log('Failed:', err);
            res.status(200).json({ "status": 0, "message": "Failed data" });
        });
}

public searchAndInsert: any = (data) => {
    // There are database operations happening here like searching for other
    // entries in the JSON and inserting to DB
    console.log('Searching and updating', data);
    return new Promise((resolve, reject) => {
        // This is not an other function its just written her to make code readable
        if(dataExistsInDB(data) == true){
            resolve(data);
        } else {
            // This is not an other function its just written her to make code readable
            insertIntoDB(data).then() => resolve(data);
        }
    });
}

I looked up in google and saw the reduce will help I would appreciate any help on how to convert this to reduce or any method you suggest (Concurrency in .map did not work)

like image 998
Akshay Venugopal Avatar asked Feb 25 '19 13:02

Akshay Venugopal


1 Answers

the Promises unfortunatelly does not allow any control of their flow. It means -> once you create new Promise, it will be doing its asynchronous parts as they like.

The Promise.all does not change it, its only purpose is that it checks all promises that you put into it and it is resolved once all of them are finished (or one of them fail).

To be able to create and control asynchronous flow, the easiest way is to wrap the creation of Promise into function and create some kind of factory method. Then instead of creating all promises upfront, you just create only one promise when you need it, wait until it is resolved and after it continue in same behaviour.

async function doAllSequentually(fnPromiseArr) {
  for (let i=0; i < fnPromiseArr.length; i++) {
    const val = await fnPromiseArr[i]();
    console.log(val);
  }
}

function createFnPromise(val) {
  return () => new Promise(resolve => resolve(val));
}

const arr = [];
for (let j=0; j < 10; j++) {
  arr.push(createFnPromise(Math.random()));
}

doAllSequentually(arr).then(() => console.log('finished'));

PS: It is also possible without async/await using standard promise-chains, but it requires to be implemented with recursion.

like image 112
libik Avatar answered Oct 04 '22 17:10

libik