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

How to process and update all models in a collection, in a single transaction, with Bookshelf?

我需要遍历 Bookshelf collection 中的所有模型,计算一些信息,然后将该信息存储回每个模型。重要的是我在单个事务中执行此操作,以便在错误时回滚。

我 运行 遇到的问题是我真正能想到的唯一方法是 Promise.map (Bluebird),但书架 collection 不行传递给地图。例如,这不起作用(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,而且书架API里好像也没有什么东西可以从一个collection...

我该怎么做?

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

第一步是编写一个函数来计算保存值,并使其成为书架模型的成员。因此,对于我的 post 中的示例,我将在扩展模型时在 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 做的事情——returns 一旦 Thing#updateSomeValue 返回的所有承诺都得到履行,returns 承诺就会兑现.

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

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