Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Execute promises map sequentially

I have written a function that is being called in a loop (map) and that function is using promises. Now, I want that function to run synchronously and exit before its next instance is called.

function t1(){
  let arr1 = [1,2,3,4,5];
  return Promise.map(arr1, (val) =>{
    const params = {
      "param1" : val1
    };
    return t2(params);
  });
}

function t2(event){
  return Promise.resolve()
  .then({
  //do something
  //code doesn't reach here in sync manner. all five instance are invoked and then code reaches here for first instance and so on
  })
  .then({
  //promise chaining. do something more
  })
}

t2 is beingcalled five times, but I want each instance to be called only after the instance before it has returned the value. Currently its not behaving like that but invoking the function five times in parallel.

I can't use async/await due to project limitations.

like image 925
user3807691 Avatar asked Aug 30 '19 07:08

user3807691


People also ask

How do you resolve promises sequentially?

You can just do Promise. resolve(files). each(fs. readFileAsync); which guarantees that promises are resolved sequentially in order.

Does Promise all run sequential?

In this approach, we will use Promise. allSettled() which will be executed in a quite similar manner as Promise. all() method executed by taking promises as input in the single array and executing them sequentially.

How do you run an array of promises?

Given an array of Promises, we have to run that in a series. To do this task, we can use then(), to run the next promise, after completion of a promise. Approach: The then() method returns a Promise, which helps us to chain promises/methods. The Promise.

Does Promise all run synchronous?

all() Method: Fulfillment: The returned promise is fulfilled, If the passed iterable is empty, then this method returns an promise synchronously which is already resolved. If all of the passed promises are fulfill, the returned Promises are fulfilled asynchronously.


2 Answers

The problem with your current code is that Promise.prototype.map, like forEach, does not wait for asynchronous functions called inside it to complete. (No asynchronous call will ever be waited for unless you tell the interpreter to do so explicitly with await or .then)

Have t1 await each call of t2:

async function t1(){
  let arr1 = [1,2,3,4,5];
  const results = [];
  for (const val of arr1) {
    results.push(await t2(val));
  }
  return results;
}

Or if you want to use reduce instead of async/await:

const delay = () => new Promise(res => setTimeout(res, 500));
function t1(){
  let arr1 = [1,2,3,4,5];
  return arr1.reduce((lastProm, val) => lastProm.then(
    (resultArrSoFar) => t2(val)
      .then(result => [...resultArrSoFar, result])
  ), Promise.resolve([]));
}

function t2(event){
  return delay().then(() => {
    console.log('iter');
    return event;
  });
}

t1()
  .then(results => console.log('end t1', results));

Or, if you need the sequential functionality to be encapsulated in t2, then have t2 have a semi-persistent variable of the previous Promise it generated:

const delay = () => new Promise(res => setTimeout(res, 500));
const t1 = () => {
  return Promise.all([1, 2, 3, 4].map(t2));
};

const t2 = (() => {
  let lastProm = Promise.resolve();
  return (event) => {
    const nextProm = lastProm
      .catch(() => null) // you may or may not want to catch here
      .then(() => {
        // do something with event
        console.log('processing event');
        return delay().then(() => event);
      });
    lastProm = nextProm;
    return nextProm;
  };
})();

t1().then(results => console.log('t1 done', results));
like image 92
CertainPerformance Avatar answered Sep 28 '22 10:09

CertainPerformance


(function loop(index) {
    const next = promiseArray[index];
    if (!next) {
        return;
    }
    next.then((response) => {
        // do Something before next
        loop(index + 1);
    }).catch(e => {
        console.error(e);
        loop(index + 1);
    });
})(0 /* startIndex */)
like image 32
Scriptkiddy1337 Avatar answered Sep 28 '22 08:09

Scriptkiddy1337