如何使用Bookshelf在单个事务中处理和更新集合中的所有模型?

时间:2016-12-13 22:52:13

标签: javascript node.js bluebird bookshelf.js

我需要迭代Bookshelf集合中的所有模型,计算一些信息,然后将这些信息存储回每个模型中。在单个事务中执行此操作非常重要,以便对错误进行回滚。

我遇到的问题是我真正想到的唯一方法是使用Promise.map(蓝鸟),但书架集合无法传递到地图。例如,这不起作用(Thing是模型,Promise是蓝鸟承诺):

Bookshelf.transaction(function (t) {
    return Thing.fetchAll({transacting:t}).then(function (things) {
        return Promise.map(things, function (thing) {
            return thing.save({
                value: computeSomeValueSync(thing)
            }, {
                transacting: t
            });
        });
    });
}).tap(function () {
    console.log("update complete");
});

因为things无法传递给Promise.map,并且Bookshelf API中似乎没有任何内容可以从集合中获取模型数组。

我该怎么做?

1 个答案:

答案 0 :(得分:0)

好吧,我至少找到了 解决方案。

第一步是编写一个计算保存值的函数,并使其成为书架模型的成员。因此,对于我的帖子中的示例,我在扩展模型时在Thing中定义了以下函数:

... = bookshelf.Model.extend({

    ...

    updateSomeValue: function (options) {
        return this.save({ 
            value: computeSomeValueSync(this)
        }, options);
    }

});

其中options是传递给保存的选项,我们可以使用它来传递事务。很容易。 然后,我们可以使用Collection#invokeThen执行等效的Promise.map,如下所示:

Bookshelf.transaction(function (t) {
    return Thing.fetchAll({transacting:t}).then(function (things) {
        return things.invokeThen("updateSomeValue", {transacting:t});
    });        
}).tap(function () {
    console.log("update complete");
});

在那里,invokeThen基本上完成了我打算用Promise.map做的事情 - 返回一个承诺,一旦履行了Thing#updateSomeValue返回的所有承诺,就会履行承诺。

由于我必须添加模型方法,这只是稍微不方便,但 至少有点意义。界面有点奇怪,因为文档很难拼凑在一起。但是,至少它是可能的。

仍然对其他想法持开放态度。