2016-12-13 1 views
1

Мне нужно перебрать все модели в коллекции Книжная полка, вычислить некоторую информацию, а затем сохранить эту информацию в каждой модели. Очень важно, чтобы я делал это в одной транзакции, для откатов от ошибок.Как обрабатывать и обновлять все модели в коллекции, в одной транзакции, с книжной полкой?

Проблема, с которой я сталкиваюсь, - это единственный способ, которым я действительно могу это сделать, - это Promise.map (Bluebird), но коллекцию книжной полки нельзя передать на карту. Например, это не работает (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 Bookshelf который может получить массив моделей из коллекции ...

Как это сделать?

ответ

0

Хорошо, я нашел a решение, по крайней мере.

Первый шаг - написать функцию, которая вычисляет , а сохраняет значение и делает его членом модели книжной полки. Так, для примера из моего поста, я бы определить следующую функцию в Thing при расширении модели:

... = bookshelf.Model.extend({ 

    ... 

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

}); 

Где options есть варианты, чтобы пройти, чтобы сохранить, которые мы можем использовать, чтобы пройти через операцию. Достаточно легко. Тогда, мы можем сделать эквивалент Promise.map с Collection#invokeThen, как это:

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 выполнены.

Это лишь слегка неудобно в том, что я должен добавить метод модели, но он делает хотя бы немного. Интерфейс немного странный, потому что документы трудно собрать вместе. Но, по крайней мере, это возможно.

Все еще открыт для других идей.

Смежные вопросы