Search code examples
javascriptarraysargumentspromisersvp.js

How to call "apply" in a promise-based setup in Javascript to pass parameters to the next then()?


I'm writing a promise-based method which takes one parameter and returns an array of values in the next step. Something like this:

foo(a).then(function (arr) {});

Inside my method foo I'm doing something like this:

foo = function (a) {

  ...

  // this will return my array
  function returnArray(my_return_array) {
    return RSVP.all(my_return_array).fail(console.log);
  }

  return requestBundleElements(a)
    .then(assembleReturnArray)
    .then(returnArray)
    .fail(console.log);
};

I'm wondering if it is possible to pass back arguments instead of an array by calling apply. So I could add another step in my promise chain and do:

  return requestBundleList(setLoadingOrder(module_list))
    .then(assembleReturnArray)
    .then(returnArray)
    .then(returnArguments)
    .fail(console.log);

with:

  function returnArguments(my_result_array) {
     //... "apply" something here
  }

Question: But as I don't have access to the "next" callback method, I can't apply. Is there any way to send back a list of parameters instead of an array to the next step?


Solution

  • This is usually called .spread and will be available natively in ES6 via destructuring. So the optimal solution that does not work at the moment is:

    foo(a).then([a,b,c] => console.log(a,b,c); /* applied array to args */);
    

    RSVP promises do not support spread out of the box at the moment, however with Bluebird or Q it would look something like:

    foo(a).spread(function(a,b,c){
          // array ["a", "b", "c"] was applied into three parameters.
    });
    

    If you're interested, you can add this yourself to RSVP:

    RSVP.Promise.prototype.spread = function(fn){
        return this.then(function(val){ // just like then
            return fn.apply(null, val); // only apply the value
        });
    };
    

    This would let you do:

    RSVP.Promise.resolve([1, 2, 3, 4]).spread(function(one, two, three, four){
        console.log(one + two + three + four); // 10
    });