Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I chain multiple conditional promises?

In my code I have conditional tasks, which all return a promise. I need the tasks to run in sequence.

My current implementation looks something like this:

var chain = [];

if (/* some condition for task A */) {
    chain.push(function(doContinue){
        taskA().then(doContinue);
    });
}

if (/* some condition for task B */) {
    chain.push(function(doContinue){
        taskB().then(doContinue);
    });
}

if (/* some condition for task C */) {
    chain.push(function(doContinue){
        taskC().then(doContinue);
    });
}

var processChain = function () {
    if (chain.length) {
        chain.shift()(processChain);
    } else {
        console.log("all tasks done");
    }
};

processChain();

This works fine, but initially I was looking for a way to create the chain using only Promises and chaining all functions using .then, but I wasn't able to get a working solution.

If there's a cleaner way using only Promises and chains of then calls, then I'd love to see an example.

like image 516
bummzack Avatar asked Nov 25 '16 11:11

bummzack


People also ask

How do you handle multiple promises?

In this approach, we will use Promise. all() method which takes all promises in a single array as its input. As a result, this method executes all the promises in itself and returns a new single promise in which the values of all the other promises are combined together.

What are the methods for chaining promises?

JavaScript Promise Chaining You can perform an operation after a promise is resolved using methods then() , catch() and finally() .

What is chaining of Promise?

Promise chaining: Promise chaining is a syntax that allows you to chain together multiple asynchronous tasks in a specific order. This is great for complex code where one asynchronous task needs to be performed after the completion of a different asynchronous task.

Which is used to take an array of promises and returns a new Promise?

The Promise.all() method takes an iterable of promises as input and returns a single Promise . This returned promise fulfills when all of the input's promises fulfill (including when an empty iterable is passed), with an array of the fulfillment values.


2 Answers

One possible approach:

var promiseChain = Promise.resolve();
if (shouldAddA) promiseChain = promiseChain.then(taskA);
if (shouldAddB) promiseChain = promiseChain.then(taskB);
if (shouldAddC) promiseChain = promiseChain.then(taskC);
return promiseChain;

Another one:

return Promise.resolve()
  .then(shouldAddA && taskA)
  .then(shouldAddB && taskB)
  .then(shouldAddC && taskC);
like image 53
raina77ow Avatar answered Oct 07 '22 08:10

raina77ow


You can use the new async/await syntax

async function foo () {
  let a = await taskA()
  if (a > 5) return a // some condition, value

  let b = await taskB()
  if (b === 0) return [a,b] // some condition, value

  let c = await taskC()
  if (c < 0) return "c is negative" // some condition, value

  return "otherwise this"
}

foo().then(result => console.log(result))

What's nice about this is – aside from the code being very flat and readable (imo) – values a, b, and c are all available in the same scope. This means your conditions and return values can depend on any combination of your tasks' promised values.

like image 36
Mulan Avatar answered Oct 07 '22 08:10

Mulan