Promise.then绑定问题
Promise.then bind issue
我在将值绑定到 next Promise 时遇到了问题。看看下面的代码,它会更好地说明情况。
'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'
});
问题是,为什么这两种情况下它绑定的值不同。两者完全一样,只是这个是先解析promise部分,然后给payload.userId
赋值。
让我们稍微分解一下您的代码。你有
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));
}
问题是您的 .bind
会 运行 在您回电之前。这段代码也可以写成
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);
}
payload
对象在所有对象之间共享,但是 payload.userId
在 firstThenCallback
有机会执行之前被传递到 .bind
。
而不是使用 .bind
并立即传递值,最简单的解决方案似乎是使用匿名函数,因此 userId
值仅在稍后读取。
function MyServiceProblem(payload) {
payload.userId = 'blah';
return FindEvent(payload.eventId)
.then((event) => {
payload.userId = 'test';
return Promise.resolve(payload);
})
.then(() => FindUser(payload.userId));
}
您也不太清楚为什么要编写这样迂回的 promise 代码,但我认为这是一个经过精简的示例?为什么要用 payload
解析而不是在该函数中调用 FindUser
,例如
function MyServiceProblem(payload) {
payload.userId = 'blah';
return FindEvent(payload.eventId)
.then((event) => {
payload.userId = 'test';
return FindUser(payload.userId);
});
}
我在将值绑定到 next Promise 时遇到了问题。看看下面的代码,它会更好地说明情况。
'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'
});
问题是,为什么这两种情况下它绑定的值不同。两者完全一样,只是这个是先解析promise部分,然后给payload.userId
赋值。
让我们稍微分解一下您的代码。你有
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));
}
问题是您的 .bind
会 运行 在您回电之前。这段代码也可以写成
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);
}
payload
对象在所有对象之间共享,但是 payload.userId
在 firstThenCallback
有机会执行之前被传递到 .bind
。
而不是使用 .bind
并立即传递值,最简单的解决方案似乎是使用匿名函数,因此 userId
值仅在稍后读取。
function MyServiceProblem(payload) {
payload.userId = 'blah';
return FindEvent(payload.eventId)
.then((event) => {
payload.userId = 'test';
return Promise.resolve(payload);
})
.then(() => FindUser(payload.userId));
}
您也不太清楚为什么要编写这样迂回的 promise 代码,但我认为这是一个经过精简的示例?为什么要用 payload
解析而不是在该函数中调用 FindUser
,例如
function MyServiceProblem(payload) {
payload.userId = 'blah';
return FindEvent(payload.eventId)
.then((event) => {
payload.userId = 'test';
return FindUser(payload.userId);
});
}