Reputation: 702
I have been facing an issue in binding a value to next Promise. Look at the following code, it will explain the situation better.
'use strict';
function FindEvent(eventId) {
console.log('Event:', eventId);
return Promise.resolve({title: 'MyEvent'});
}
function FindUser(userId) {
console.log('User:', userId);
return Promise.resolve({username: 'MyUser'});
}
function MyServiceProblem(payload) {
payload.userId = 'blah';
return FindEvent(payload.eventId)
.then((event) => {
payload.userId = 'test';
// setting a breakpoint here shows
// that the value to payload.userId has been
// assigned, i.e. 'test'
return Promise.resolve(payload);
})
.then(FindUser.bind(this, payload.userId));
// But new value doesn't reaches inside FindUser
}
MyServiceProblem({ // userId is 'blah', why not 'test'
eventId: '456'
});
function MyServiceWorks(payload) {
payload.userId = 'blah';
return new Promise((resolve) => {
payload.userId = 'test';
return resolve(payload);
})
.then(FindUser.bind(this, payload.userId));
// From here, the 'test' value reaches FindUser
}
MyServiceWorks({ // userId is 'test'
eventId: '456'
});
The question is, why the value it binds is different for both cases. Both are exactly the same, except this one is first resolving the part of promise and then assigning a value to payload.userId
.
Upvotes: 0
Views: 2114
Reputation: 161557
Let's break down your code a little bit. You have
function MyServiceProblem(payload) {
payload.userId = 'blah';
return FindEvent(payload.eventId)
.then((event) => {
payload.userId = 'test';
return Promise.resolve(payload);
})
.then(FindUser.bind(this, payload.userId));
}
the issue is that your .bind
will run before your callback. This code could also be written as
function MyServiceProblem(payload) {
payload.userId = 'blah';
var firstThenCallback = (event) => {
payload.userId = 'test';
return Promise.resolve(payload);
};
var secondThenCallback = FindUser.bind(this, payload.userId);
return FindEvent(payload.eventId)
.then(firstThenCallback)
.then(secondThenCallback);
}
The payload
object is shared across everything, but the payload.userId
is passed into .bind
before firstThenCallback
has had a chance to execute.
Rather that using .bind
and passing the value immediately, it seems like your simplest solution would be to use an anonymous function so the userId
value is only read later.
function MyServiceProblem(payload) {
payload.userId = 'blah';
return FindEvent(payload.eventId)
.then((event) => {
payload.userId = 'test';
return Promise.resolve(payload);
})
.then(() => FindUser(payload.userId));
}
It's not at all clear why you've written such round-about promise code either, but I assume this is a trimmed-down example? Why are you resolving with payload
instead of just calling FindUser
in that function, e.g.
function MyServiceProblem(payload) {
payload.userId = 'blah';
return FindEvent(payload.eventId)
.then((event) => {
payload.userId = 'test';
return FindUser(payload.userId);
});
}
Upvotes: 3