Skip to content Skip to sidebar Skip to footer

Javascript: Horizontal Chaining Promises Without Multiple Then Calls

Is there a short inbuilt way to do horizontal promise chaining? The usual way to chain steps is: (async()=>1)().then(_=>{ //etc.. return _+_ }).then(_=>{ //etc.. r

Solution 1:

As others have said there is no built in way to do this. The following code might be of interest though.

There is a concept known as 'lifting' whereby you transform a function into one that works on wrapped values. In this case promises. It would look something like this:

constlift = (fn) => (promise) => promise.then(fn);

There is also the idea of chaining together a list of functions, composing them with one another. Like this:

constchain = (...fns) => (value) => fns.reduce((result, fn) =>fn(result), value)

Together, these tools allow you to rewrite your code as:

chain(
  lift(_=>++_),
  lift(_=>_*=_),
  lift(_=>alert(_))
)((async()=>1)())

Which alerts 4 as expected.

I'm also a little confused by your use of ++_ and _*=_ because they imply you wish to mutate the variable. Because of how your code is structured it would be a better display of intent to use _+1 and _*_

Solution 2:

Using Array.reduce(), you can combine the series of functions into a promise chain using the following static function:

functionseries (initial, ...callbacks) {
  return callbacks.reduce(
    (chain, callback) => chain.then(callback),
    Promise.resolve(initial)
  )
}

series(1, _=>_+1, _=>_*_, alert)

For convenience, you could define this as Promise.series() like this:

Object.defineProperty(Promise, 'series', {
  configurable: true,
  value: functionseries (initial, ...callbacks) { ... },
  writable: true
})

Lastly, in ES2017, you could alternatively use async / await to write it like this:

asyncfunctionseries(initial, ...callbacks) {
  let value = await initial

  for (const callback of callbacks) {
    value = awaitcallback(value)
  }

  return value
}

series(1, _=>_+1, _=>_*_, alert)

Solution 3:

You can use rest parameter to pass N functions to a function which return a Promise to be called in sequence with the previous Promise value set to parameter passed to the current function call until no elements remain in array using async/await and repeated scheduling of the same procedure

consta = n => newPromise(resolve =>setTimeout(resolve, Math.floor(Math.random() * 1000), ++n));

constb = n => newPromise(resolve =>setTimeout(resolve, Math.floor(Math.random() * 1000), n * n));

const F = async(n, ...fns) => {
  try {
    while (fns.length) n = await fns.shift()(n);
    alert(n);
  } catch (err) {
    throw err
  }
  return n
}

F(1, a, b)
.then(n =>console.log(n))
.catch(err =>console.error(err));

Solution 4:

Given that the code at Question is synchronous you can use the code at Question

((_) => (_++, _*=_, alert(_)) )(1)

Or use async/await

(async(_) => (_ = await _, _++, _ *= _, alert(_)))(Promise.resolve(1))

Post a Comment for "Javascript: Horizontal Chaining Promises Without Multiple Then Calls"