Passing more than single value through promise chain

How to store multiple values in a promise chain using an object.

Promises are fulfilled (resolved or rejected) with a single value. If we need to keep track of multiple values we can return several values as an array, even using .spread method for convenience

1
2
3
4
5
6
7
8
promise
.then(function (x) {
// compute y
return [x, y];
})
.spread(function (x, y) {
// keep accumulating values
});

Passing multiple values using separate arguments quickly becomes cumbersome. Some promise implementation, for example AngularJS $q do not implement .spread method, forcing to use an array argument

1
2
3
4
5
6
7
8
$qPromise
.then(function (x) {
return [x, y];
})
.then(function (results) {
// results[0] => x
// results[1] => y
});

We can use a helper method that takes a function expecting separate arguments and create new function that splits an array.

1
2
3
4
5
6
7
8
9
10
11
12
function spread(fn) {
return function (arr) {
return fn.apply(null, arr);
};
}
$qPromise
.then(function (x) {
return [x, y];
})
.then(spread(function (x, y) {
// convenient
}));

Even when .spread method is available, passing all values through every function is inconvenient. We might generate a value Z at the step N and use it only at the step N + K. It would be nice to avoid passing the value Z through functions at steps N + 1 through N + K - 1.

I use a separate object for this. Since the promise chain is usually constructed inside a function, the separate object is a local variable scoped to the function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function action() {
var data = {};
return promise
.then(function () {
var x = // generate x
var y = // generate y
// we might need x and y somewhere down the road
data.x = x;
data.y = y;
// the next step in the chain only needs the x + y sum
return x + y;
})
.then(function (sum) {
console.log('sum =', sum);
})
.then(function printXandY() {
// now use x and y
console.log('x =', data.x, 'y =', data.y);
});

If we want, we could return the full object in the last step of the promise chain.