Say I have a step in a procedure that requires the retrieval of two objects. I would use join()
to coordinate the retrievals:
return promise.join(retrieveA(), retrieveB())
.spread(function(A, B) {
// create something out of A and B
});
The documentation shows that you can also pass the handler as the last parameter:
return promise.join(retrieveA(), retrieveB(), function(A, B) {
// create something out of A and B
});
I'm curious as to what the rationale behind the existence of this option.
Say I have a step in a procedure that requires the retrieval of two objects. I would use join()
to coordinate the retrievals:
return promise.join(retrieveA(), retrieveB())
.spread(function(A, B) {
// create something out of A and B
});
The documentation shows that you can also pass the handler as the last parameter:
return promise.join(retrieveA(), retrieveB(), function(A, B) {
// create something out of A and B
});
I'm curious as to what the rationale behind the existence of this option.
Share Improve this question edited Apr 13, 2015 at 16:32 ItalyPaleAle 7,3066 gold badges48 silver badges74 bronze badges asked Apr 13, 2015 at 16:27 cleongcleong 7,6064 gold badges32 silver badges41 bronze badges 1- Why don't you ask the author? E.g. github.com/petkaantonov/bluebird/issues – Felix Kling Commented Apr 13, 2015 at 16:30
2 Answers
Reset to default 13Fact time: The reason .join
was added was to make @spion happy. Not without reason though, using .join
means you have a static and known number of promise which makes using it with TypeScript a lot easier. Petka (Esailija) liked the idea and also the fact it can be optimised further because it doesn't have to abide to weird guarantees the other form does have to abide to.
Over time, people started (at least me) using it for other use cases - namely using promises as proxies.
So, let's talk about what it does better:
Static Analysis
It's hard to statically analyse Promise.all
since it works on an array with an unknown types of promises of potentially different types. Promise.join
can be typed since it can be seen as taking a tuple - so for example for the 3 promises case you can give it a type signature of (Promise<S>, Promise<U>, Promise<T>, ((S,U,T) -> Promise<K> | K)) -> Promise<K>
which simply can't be done in a type safe way for Promise.all
.
Proxying
It's very clean to use when writing promise code in the proxying style:
var user = getUser();
var comments = user.then(getComments);
var related = Promise.join(user, comments, getRelated);
Promise.join(user, comments, related, (user, comments, related) => {
// use all 3 here
});
It's faster
Since it doesn't need to produce the value of the given promises cached and to keep all the checks .all(...).spread(...)
does - it'll perform slightly faster.
But... you really usually shouldn't care.
you can also pass the handler as the last parameter. I'm curious as to what the rationale behind the existence of this option.
It is not an "option". It's the sole purpose of the join
function.
Promise.join(promiseA, promiseB, …, function(a, b, …) { … })
is exactly equivalent to
Promise.all([promiseA, promiseB, …]).spread(function(a, b, …) { … })
But, as mentioned in the documentation, it
is much easier (and more performant) to use when you have a fixed amount of discrete promises
It relieves you of needing to use that array literal, and it doesn't need to create that intermediate promise object for the array result.