如何通过中间阶段传递 promise 结果
How to pass promise results through intermediate stages
我试图在承诺的步骤之间传递中间值,但我找不到一种干净的方法来做到这一点。作为一个用例,这似乎很常见,所以我希望我只是缺少一种模式,而不是完全偏离轨道。
我将 Bluebird 用于 promises 和 Sequelize (SQL ORM)。
示例代码:
db.sync().then(function () {
// When DB ready, insert some posts
return [
BlogPost.create(),
BlogPost.create()
];
}).spread(function (post1, post2) {
// Once posts inserted, add some comments
return [
post1.createComment({ content: 'Hi - on post 1' }),
post2.createComment({ content: 'Hi - on post 2' })
];
}).spread(function (post1, post2) { // THE PROBLEM: Want posts here, not comments
// Do more with posts after comments added, e.g. add tags to the posts
// Can't do that in the above as something needs to wait for
// comment creation to succeed successfully somewhere.
// Want to wait on Comments promise, but keep using Posts promise result
});
我目前最好的解决方案是:
db.sync().then(function () {
// When DB ready, insert some posts
return [
BlogPost.create(),
BlogPost.create()
];
}).spread(function (post1, post2) {
// Once posts inserted, add some comments
return Promise.all([
post1.createComment({ content: 'Hi - on post 1' }),
post2.createComment({ content: 'Hi - on post 2' })
]).then(function () {
// Extra nested promise resolution to pull in the previous results
return [post1, post2];
});
}).spread(function (post1, post2) {
// Do things with both posts
});
当然还有更好的方法吗? Bluebird 有 .tap(),非常接近,但没有做 spread() 部分,我找不到一个简单的方法来组合。
我关闭了这个但又重新打开了,因为你的问题比一般问题具体得多。 关于一般问题。
对于 one-action-above 的特定上下文 - 您可以使用 .return
和 bluebird 来覆盖 return 值:
db.sync().then(function () {
...
}).spread(function (post1, post2) {
return Promise.all([
post1.createComment({ content: 'Hi - on post 1' }),
post2.createComment({ content: 'Hi - on post 2' })
]).return([post1, post2]); // use .return here
}).spread(function (post1, post2) { comments
// posts here
});
经过更多调查,我仍然找到了更好的答案(0 promise 嵌套):
db.sync().then(function () {
// When DB ready, insert some posts
return [
BlogPost.create(),
BlogPost.create()
];
}).all().tap(function (posts) {
// Once posts inserted, add some comments
return [
posts[0].createComment({ content: 'Hi - on post 1' }),
posts[1].createComment({ content: 'Hi - on post 2' })
]
}).spread(function (post1, post2) {
// Do things with both posts
});
注意 tap 之前的 .all() :这确保第一个 then() 的结果在到达 tap() 之前正确展开,并允许您正常使用 tap。仍然没有给你 spread() 支持,但它已经足够接近了。
我试图在承诺的步骤之间传递中间值,但我找不到一种干净的方法来做到这一点。作为一个用例,这似乎很常见,所以我希望我只是缺少一种模式,而不是完全偏离轨道。
我将 Bluebird 用于 promises 和 Sequelize (SQL ORM)。
示例代码:
db.sync().then(function () {
// When DB ready, insert some posts
return [
BlogPost.create(),
BlogPost.create()
];
}).spread(function (post1, post2) {
// Once posts inserted, add some comments
return [
post1.createComment({ content: 'Hi - on post 1' }),
post2.createComment({ content: 'Hi - on post 2' })
];
}).spread(function (post1, post2) { // THE PROBLEM: Want posts here, not comments
// Do more with posts after comments added, e.g. add tags to the posts
// Can't do that in the above as something needs to wait for
// comment creation to succeed successfully somewhere.
// Want to wait on Comments promise, but keep using Posts promise result
});
我目前最好的解决方案是:
db.sync().then(function () {
// When DB ready, insert some posts
return [
BlogPost.create(),
BlogPost.create()
];
}).spread(function (post1, post2) {
// Once posts inserted, add some comments
return Promise.all([
post1.createComment({ content: 'Hi - on post 1' }),
post2.createComment({ content: 'Hi - on post 2' })
]).then(function () {
// Extra nested promise resolution to pull in the previous results
return [post1, post2];
});
}).spread(function (post1, post2) {
// Do things with both posts
});
当然还有更好的方法吗? Bluebird 有 .tap(),非常接近,但没有做 spread() 部分,我找不到一个简单的方法来组合。
我关闭了这个但又重新打开了,因为你的问题比一般问题具体得多。
对于 one-action-above 的特定上下文 - 您可以使用 .return
和 bluebird 来覆盖 return 值:
db.sync().then(function () {
...
}).spread(function (post1, post2) {
return Promise.all([
post1.createComment({ content: 'Hi - on post 1' }),
post2.createComment({ content: 'Hi - on post 2' })
]).return([post1, post2]); // use .return here
}).spread(function (post1, post2) { comments
// posts here
});
经过更多调查,我仍然找到了更好的答案(0 promise 嵌套):
db.sync().then(function () {
// When DB ready, insert some posts
return [
BlogPost.create(),
BlogPost.create()
];
}).all().tap(function (posts) {
// Once posts inserted, add some comments
return [
posts[0].createComment({ content: 'Hi - on post 1' }),
posts[1].createComment({ content: 'Hi - on post 2' })
]
}).spread(function (post1, post2) {
// Do things with both posts
});
注意 tap 之前的 .all() :这确保第一个 then() 的结果在到达 tap() 之前正确展开,并允许您正常使用 tap。仍然没有给你 spread() 支持,但它已经足够接近了。