How do you properly return multiple values from a Promise?

You can return an object containing both values — there's nothing wrong with that.

Another strategy is to keep the value, via closures, instead of passing it through:

somethingAsync().then(afterSomething);

function afterSomething(amazingData) {
  return processAsync(amazingData).then(function (processedData) {
    // both amazingData and processedData are in scope here
  });
}

Fully rather than partially inlined form (equivalent, arguably more consistent):

somethingAsync().then(function (amazingData) {
  return processAsync(amazingData).then(function (processedData) {
    // both amazingData and processedData are in scope here
  });
}

you can only pass one value, but it can be an array with multiples values within, as example:

function step1(){
  let server = "myserver.com";
  let data = "so much data, very impresive";
  return Promise.resolve([server, data]);
}

on the other side, you can use the destructuring expression for ES2015 to get the individual values.

function step2([server, data]){
  console.log(server); // print "myserver.com"
  console.log(data);   // print "so much data, very impresive"
  return Promise.resolve("done");
}

to call both promise, chaining them:

step1()
.then(step2)
.then((msg)=>{
  console.log(msg); // print "done"
})

You can't resolve a promise with multiple properties just like you can't return multiple values from a function. A promise conceptually represents a value over time so while you can represent composite values you can't put multiple values in a promise.

A promise inherently resolves with a single value - this is part of how Q works, how the Promises/A+ spec works and how the abstraction works.

The closest you can get is use Q.spread and return arrays or use ES6 destructuring if it's supported or you're willing to use a transpilation tool like BabelJS.

As for passing context down a promise chain please refer to Bergi's excellent canonical on that.


Two things you can do, return an object

somethingAsync()
    .then( afterSomething )
    .then( afterSomethingElse );

function processAsync (amazingData) {
     //processSomething
     return {
         amazingData: amazingData, 
         processedData: processedData
     };
}

function afterSomething( amazingData ) {
    return processAsync( amazingData );
}

function afterSomethingElse( dataObj ) {
    let amazingData = dataObj.amazingData,
        processedData = dataObj.proccessedData;
}

Use the scope!

var amazingData;
somethingAsync()
  .then( afterSomething )
  .then( afterSomethingElse )

function afterSomething( returnedAmazingData ) {
  amazingData = returnedAmazingData;
  return processAsync( amazingData );
}
function afterSomethingElse( processedData ) {
  //use amazingData here
}