Reputation: 871
the documentation says that chaining of promises works like
return getUsername()
.then(function (username) {
return getUser(username);
})
.then(function (user) {
wouldn't it be nice if the following would work as well?
return getUsername()
.then(getUser)
.then(function (user) {
I stumbled upon it because this is what I intuitively did and it didn't work.
thanks a lot
Upvotes: 1
Views: 647
Reputation: 276596
Yes, it works.
There are two reasons it might fail: variable vs function hoisting or dynamic this
.
A difference between:
var foo = bar;
And:
var foo = function(x){ return bar(x); }
Given it's bar's signature is that in the second snippet bar
is lazily evaluated. So if bar
is undefined you'll get an error in the first example but not the second. Most promise libraries ignore (and have to because of the specification) undefined
passed to then
and simply return the same promise.
This issue in your example might look like:
return getUsername()
.then(function (username) {
return getUser(username); // note it's a method
})
.then(function (user) { ...
// later on in the file after the function ended
var getUser = function(){
// because of the function wrap above, this will work since
// the function(){ causes it to be lazily evaluated
};
On the other hand doing:
return getUsername()
.then(getUser)
.then(function (user) {
// later on in the file outside the function
var getUser = function(username){
// code here
};
Is the same as doing:
return getUsername()
.then(undefined) // remember, promises ignore this
.then(function (user) {
This has to do with how JavaScript handles hoisting of variables vs. hosting of function declarations.
The reason it's not working is that your code actually looks a bit different. Your code is more like:
return getUsername()
.then(function (username) {
return someObj.getUser(username); // note it's a method
})
.then(function (user) {
And in fact getUser
is accessing this
inside it - this makes this an unbound function which depends on this
. Remember that JavaScript has dynamic this
so you can't simply do:
return getUsername()
.then(someObj.getUser) // this won't work, pun intended
.then(function (user) {
Now, in order to make it work - you can bind it for example:
return getUsername()
.then(someObj.getUser.bind(someObj) // IE9+
.then(function (user) {
// if using bluebird, this is faster:
return getUsername().bind(someObj)
.then(someObj.getUser)
.then(function (user) {
Or use the longer version with the function expression.
This might not be your specific issue - but 9 out of 10 times someone asks this - it solves their problem.
Upvotes: 1