2015-08-20 2 views
1

У меня есть пользовательский класс модели, в которой у меня есть свойство, которое говорит мне, когда модель была последней неправдоподобной:Задержка Backbone.sync события

var MyModel = Backbone.Model.extend({ 
    fetched: null, 
    fetch: function(options) { 
     var self = this; 
     return Backbone.Model.prototype.fetch 
      .apply(this, arguments) 
      .done(function(){ 
       self.fetched = _.now(); 
      }); 
    } 
}); 

Затем мой взгляд слушает change событий этой модели и делает себя когда это происходит, с другим результатом в зависимости от того, модель была неправдоподобной или нет:

var MyView = Backbone.View.extend({ 
    initialize: function() { 
     this.listenTo(this.model, 'change', this.render); 
    }, 
    render: function() { 
     if (this.model.fetched == null) { 
      // Do something 
     } 
     else { 
      // Do something else 
     } 
     return this; 
    } 
}); 

Моей проблема заключается в том, что change событие срабатывает как только Model.fetch завершаются, даже до того, как установить self.fetched = _.now(). Я знаю, что в данный момент я могу запустить событие вручную, но это было бы лишним, и я не уверен, что модель действительно изменилась во время этой выборки.

Есть ли способ поймать события, которые были вызваны во время разговора, до Backbone.Model.prototype.fetch, чтобы я мог запускать их вручную в моем цепном done?

Обновление: Или есть способ дать fetch функцию, которая будет работать при успешном запуске событий?

+0

Это не то, для чего предназначалось, но переопределение [parse] (http://backbonejs.org/#Model-parse) позволит вам запустить код до того, как данные будут применены к модели. – ivarni

+0

@ivarni Да, из того, что я вижу в источнике, это единственное место, где я могу * вставлять * инструкции непосредственно перед запуском события «change» (см. Строку 592 [здесь] (https://github.com/jashkenas /backbone/blob/00f8b6fe797321131f76a72e95560ad2354c5dc9/backbone.js#L592), событие запускается при выполнении 'model.set (serverAttrs, options))'). Однако в этот момент я буду знать, что данные были успешно получены с сервера, но не в том случае, если он был успешно установлен в модель. Я начинаю думать, что единственный способ добиться того, что я хочу, это переписать «Backbone.Model.fetch». – arnaudrg

ответ

0

Вы можете снабдить функцию выборки успешным обратным вызовом, и вы можете избавиться от кода в своей модели.

var MyView = Backbone.View.extend({ 
 
    initialize: function() { 
 
     var self=this 
 
     this.listenTo(this.model, 'change', this.render); 
 
     this.model.fetch({ 
 
      success: function(){ 
 
       self.model.fetched= _.now(); 
 
     }) 
 
    }, 
 
    render: function() { 
 
     if (this.model.fetched == null) { 
 
      // Do something 
 
     } 
 
     else { 
 
      // Do something else 
 
     } 
 
     return this; 
 
    } 
 
});

+0

Я вижу две проблемы с этим решением: я должен делать это во всех представлениях, которые слушают мою модель, и она не будет работать, если модель будет обновлена ​​после визуализации представления. – arnaudrg

1

Выбор времени, потому что .done() обработчик пожары в более позднем потоке событий, похожих на setTimeout().

Есть ли способ поймать события, которые были вызваны во время вызова Backbone.Model.prototype.fetch, чтобы я мог запускать их вручную в моей цепочке?

Нет, я ожидаю, без взлома Магистраль, которую вы действительно не хотите делать. Однако вы можете использовать способность Backbone запускать и прослушивать пользовательские события.

Например, у вас может быть пользовательское событие fetched, вызванное обратным вызовом .done() в MyModel.fetch() и прослушивается везде, где вам нравится.

Потребность в вашей отметке времени MyModel.model.fetched исчезнет, ​​потому что, в отличие от change, пользовательское событие будет запускаться только из одного места.

var MyModel = Backbone.Model.extend({ 
    fetch: function(options) { 
     var self = this; 
     return Backbone.Model.prototype.fetch 
      .apply(this, arguments) 
      .done(function() { 
       self.trigger('fetched'); 
      }); 
    } 
}); 

Хотя документация переговоров пользовательских событий только в связи с .on(), они в равной степени могут быть выслушаны с .listenTo(). И вам нечего мешать слушать стандарт change, а также обычное событие fetched.

Эта стратегия позволила бы (например) ваш «Сделай что-нибудь» и «Есть ли что-то еще» должны быть выполнены в виде отдельных слушателей, а не как ветви одного слушателя:

var MyView = Backbone.View.extend({ 
    initialize: function() { 
     this.listenTo(this.model, 'change', this.render_on_change); 
     this.listenTo(this.model, 'fetched', this.render_on_fetch); 
    }, 
    render_on_change: function() { 
     /* Do something */ 
    }, 
    render_on_fetch: function() { 
     /* Do something else */ 
    } 
}); 

Вариации бесконечны ,Вам, вероятно, придется поиграть с ним, пока не получите именно то, что подходит вашему приложению.

Чтобы ввести this.listenTo(this.model, 'fetched', ...);, я боюсь, вам придется укусить пулю и внести изменения в каждое представление, которое должно отвечать на это событие. Это неизбежно.

При положительном рассмотрении любые модели, которые в настоящее время имеют this.listenTo(this.model, 'change', ...); и не нуждаются в прослушивании fetched, могут оставаться такими, как они есть.

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