如何通过中间阶段传递承诺结果

时间:2015-06-24 13:45:33

标签: javascript promise sequelize.js bluebird

我试图在承诺的步骤之间传递中间值,但我找不到干净的方法。这似乎是一个很常见的用例,所以我希望我只是错过了一个模式,而不是完全偏离轨道。

我使用Bluebird作为承诺,使用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
});

当然,还有更好的方法吗?蓝鸟有.tap(),它非常接近,但没有做spread()部分,我找不到一种简单的方法来组合。

2 个答案:

答案 0 :(得分:1)

我关闭了这个,但后来重新打开,因为你的问题比通用问题更具体。关于一般问题Make sure your read this question and answers

对于上述单一操作的特定上下文,您可以使用.return与bluebird覆盖返回值:

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
});

答案 1 :(得分:0)

经过一番调查后,我仍然找到了一个更好的答案(0承诺嵌套):

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
});

在点击之前注意.all():这可以确保在到达tap()之前正确解开first then()的结果,并允许您正常使用tap。仍然没有给你spread()支持,但它足够接近。