我一直面临着将值绑定到下一个 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'
});
问题是,为什么它绑定的值对于这两种情况都是不同的。两者都完全相同,除了这个是首先解决承诺的部分,然后给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));
}
也完全不清楚你为什么要写这么迂回的承诺代码,但我认为这是一个精简的例子?为什么要用payload
解决,而不仅仅是在该函数中调用FindUser
,例如
function MyServiceProblem(payload) {
payload.userId = 'blah';
return FindEvent(payload.eventId)
.then((event) => {
payload.userId = 'test';
return FindUser(payload.userId);
});
}