2

Here I have 4 functions that return promises. If you run hello and pass each on into the next .then you get one long string.

var hello = function(str){
  return Promise.resolve(str+ "hello")
}
var world = function(str){
  return Promise.resolve(str+ "world")
}
var foo = function(str){
  return Promise.resolve(str+ "foo")
}
var bar = function(str){
  return Promise.resolve(str+ "bar")
}

// hello("alpha").then(world).then(foo).then(bar).then(console.log)
// => alphahelloworldfoobar

I'd like to be able to pass a flat array of the functions into a function and get return a function that has them all nested.

var arr = wrapThen([
  hello,
  world,
  foo,
  bar
])

arr("alpha").then(console.log)

Is this possible? Does bluebird offer this?

This is what I hacked together:

function wrapThen(arr){
  var headPromise = arr.shift()
  return function(){
    var args = _.values(arguments)
    var init = headPromise(args)
    var values = []
    return Promise.each(arr, function(item){
      init = init.then(item)
      return init.then(function(value){
        values.push(value)
        return value
      })
    }).then(function(){
      return _.last(values)
    })
  }
}

3 Answers 3

2

Sure, this is pretty easy with bluebird, with a reduce, this is fundamentally what a reduce does anyway (aggregate result):

let result = Promise.reduce([hello, world, foo, bar], function(result, action){
    return action(result);
}, "alpha");

In ES2015 notation this becomes even less verbose:

let {reduce} = Promise;
let result = reduce(arr, (result, action) => action(result), "alpha");

var hello = function(str){
  return Promise.resolve(str+ "hello");
};
var world = function(str){
  return Promise.resolve(str+ "world");
};
var foo = function(str){
  return Promise.resolve(str+ "foo");
};
var bar = function(str){
  return Promise.resolve(str+ "bar");
};


Promise.reduce([hello, world, foo, bar], function(result, action){
    return action(result);
}, "alpha").then(function(endResult){ 
    console.log(endResult);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/bluebird/2.9.33/bluebird.min.js"></script>

Sign up to request clarification or add additional context in comments.

Comments

0

Not sure you want all function to get same param alpha or still pass as sequence, so I write both, just use .reduce and .map you can achieve both way.

var hello = function(str){
  return Promise.resolve(str+ "hello");
};
var world = function(str){
  return Promise.resolve(str+ "world");
};
var foo = function(str){
  return Promise.resolve(str+ "foo");
};
var bar = function(str){
  return Promise.resolve(str+ "bar");
};
 
// Wrap all functions in list, all give them the same value.
var wrapToArray = function(list) {
  
  return function(result) {
    var allP = list.map(function(item) {
      return item(result);
    });
    return Promise.all(allP);
  };
  
};

// Wraps all, and resolve them by array's sequence.
var wrapToSequence = function(list) {
  
   return  function(result) {
    // Create a promise that resolved with result first.
    var promise = Promise.resolve(result);
    // Use reduce to chain the functions.
    promise = list.reduce(function(prev, item) {
      return prev.then(item);
    }, promise);
    return promise;
  };

};

var arr = wrapToArray([hello, world, foo, bar]);
var arr2 = wrapToSequence([hello, world, foo, bar]);

arr("alpha").then(console.log.bind(console));
arr2("alpha").then(console.log.bind(console));
<script src="https://cdnjs.cloudflare.com/ajax/libs/bluebird/2.9.33/bluebird.min.js"></script>

Bluebird also provide .reduce, .map to create it easier, to avoid the answer become longer, demo is on jsfiddle.

var wrapToSequence = function(list) {
   return  function(result) {
    return  Promise.reduce(list, function(result, fn) {
      return fn(result);
    }, result);
  };
};

var wrapToArray = function(list) {
  return function(result) {
    return Promise.map(list, function(fn) {
      return fn(result);
    });
  };
};

Comments

0

Here's an example of how to do this using Ramda.

var R = require("ramda")

var hello = function(str){
  return Promise.resolve(str+ "hello")
}
var world = function(str){
  return Promise.resolve(str+ "world")
}
var foo = function(str){
  return Promise.resolve(str+ "foo")
}
var bar = function(str){
  return Promise.resolve(str+ "bar")
}

var result = R.pipeP(hello, world, foo, bar)

result("alpha").then(console.log) // logs -> "alphahelloworldfoobar"

result("alpha") // promise -> "alphahelloworldfoobar"

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.