2

I'm trying to have a series of promises executed synchronously, chaining them together, but only having certain promises added based on a condition..

Heres an example of what I mean:

const Promise = require('bluebird')

const funcA = int => new Promise( res => res(++int) )
const funcB = int => new Promise( res => res(++int) )
const funcC = int => new Promise( res => res(++int) )

let mainPromise = funcA(1)

// Only execute the funcB promise if a condition is true
if( true )
    mainPromise = mainPromise.then(funcB)

mainPromise = mainPromise.then(funcC)

mainPromise
    .then( result =>  console.log('RESULT:',result))
    .catch( err => console.log('ERROR:',err))

If the boolean is true, then the output is: RESULT: 4, if its false, then its RESULT: 3, which is exactly what I'm trying to accomplish.

I figured there should be a better, cleaner way to do this though. I'm using the Bluebird promise library, which is pretty powerful. I tried using Promise.join, which didn't yield the desired result, and neither did Promise.reduce (But I may have been doing that one incorrectly)

Thanks

Justin
  • 1,959
  • 5
  • 22
  • 40
  • Can you show us how you've used `Promise.reduce`? – Bergi Feb 13 '16 at 18:38
  • Just a nitpick, but [promises are not executed](http://stackoverflow.com/a/30823708/1048572) – Bergi Feb 13 '16 at 18:40
  • Do you want to evaluate the condition at the time that `funcA()` has settled, or is that statically known when building the chain (like in your example)? Or does it not matter? – Bergi Feb 13 '16 at 18:42

2 Answers2

1

You're chaining asynchronous functions. Think of promises more as return values, not that exciting.

You could put the functions in an array like this, then filter the array:

[funcA, funcB, funcC]
  .filter(somefilter)
  .reduce((p, func) => p.then(int => func(int)), Promise.resolve(1))
  .catch(e => console.error(e));

Or if you're just looking for a better way to write with conditions in a sequence, you might do this:

funcA(1)
  .then(int => condition ? funcB(int) : int)
  .then(funcC);
  .catch(e => console.error(e));

And if you're using ES7 you can use async functions:

async function foo() {
  var int = await funcA(1);
  if (condition) {
    int = await funcB(int);
  }
  return await funcC(int);
}
jib
  • 40,579
  • 17
  • 100
  • 158
  • Alternatively, he might want to do `.then(condition ? funcB : (int => int))` – Bergi Feb 13 '16 at 21:17
  • Right, I know they're asynchronous, I meant I wanted the promises to be executed in a specific order, passing the resolved data from one to the other. - For your first example, it would work just pushing the `func*` to the array, and not using the filter right? And is there a way to define a parameter for the first one? – Justin Feb 14 '16 at 03:15
  • I just found [this thread](http://stackoverflow.com/questions/30732880/chain-array-of-promises-with-bluebird?rq=1) seems to have a good answer... (I just found that under the related links) – Justin Feb 14 '16 at 03:20
  • Right. I've edited the answer to pass in `1` as the initial value to `reduce`. – jib Feb 14 '16 at 05:40
0

I found a good related thread here. Using the same logic, I was able to get this working:

const Promise = require('bluebird')

const funcA = int => new Promise( res => res(++int) )
const funcB = int => new Promise( res => res(++int) )
const funcC = int => new Promise( res => res(++int) )

const toExecute = [funcA, funcB]

if( !!condition )
    toExecute.push( funcC )

Promise.reduce( toExecute, ( result, currentFunction ) => currentFunction(result), 1)
    .then( transformedData => console.log('Result:', transformedData) )
    .catch( err => console.error('ERROR:', err) )

Same results as posted in my original thread

Community
  • 1
  • 1
Justin
  • 1,959
  • 5
  • 22
  • 40