我怎么知道我的逆火收集何时从服务器加载完毕?

时间:2013-03-07 04:08:39

标签: firebase backfire

我正在玩firebase并适得其反。 example没有明确说明,但我发现当你实例化Backbone.Firebase.Collection的实例时,它会从服务器加载数据。 E.g:

var TodoList = Backbone.Collection.extend({
  model: Todo,
  firebase: new Backbone.Firebase("https://<your-namespace>.firebaseio.com")
});
var todos = new TodoList(); // fetches data

我如何知道检索何时完成?

2 个答案:

答案 0 :(得分:8)

与Backfire的模型进行了广泛的合作,我对此有几点想法。我希望他们中的一些人能为你的项目提供好的建议。

将心智模型更改为实时环境

首先,摆脱了解“所有数据都被加载”的心态,假设这会让你很早就遇到麻烦。我们现在处于实时环境中。从零开始,将每个记录作为更新处理。这样可以节省大量的时间和精力来处理各州。

延迟呈现和DOM绑定

现在使用Backbone,我经常发现自己想做一个懒惰的渲染。也就是说,我想逻辑地处理以下条件:

  • 立即开始收集数据,但在调用render之前不显示数据
  • 显示“加载”消息,直到出现一些数据
  • 当多个记录靠近在一起时,不要为每一个记录重新呈现

经常更改数据的一个很好的解决方案是Backbone.ModelBinder的CollectionBinder tool,它可以单独操作DOM的每个节点,而不是重新渲染所有记录。他们的网站上有很多例子,所以我不会在这里详细介绍。

辩论作为快速而肮脏的解决方案

Underscore的debounce方法对于不需要数据绑定的所有复杂性的小规模DOM操作来说是一个很好的解决方案。等待大约250的去抖动对我来说很有效,确保渲染始终在数据更改时发生,但如果我们连续获得大量更新,则只进行一次。

假设我们创建了一个扩展Backbone.Firebase.Collection的集合,那么我们可以执行以下操作:

var View = Backbone.View.extend({

   initialize: function() {
      this.listenTo( this.collection, 'add remove', _.debounce(_.bind(this.dataChanged, this), 250) );
   },

   render: function() {
       this._isRendered = true;

       /* do all my rendering magic here */
   },


   dataChanged: function() {
      // wait until render has been called at least once
      // if so, re-render on any change
      this._isRendered && this.render();
   }
});

使用延迟等待加载的数据

在Backfire的实现上,我添加了一个有状态的方法,在第一次加载时通知我。我是使用jQuery的Deferred对象完成的。然后我只是听取集合来发起sync事件:

this.collection.once('sync', /* data is loaded */);

Firebase的一个好处是,最初的Firebase.on('child_added'...)结果(现有记录)倾向于出现在一个漂亮的大块中 - 一个接一个。所以作为一个额外的奖励,我使用去抖动使我的“加载”方法在初始丛完成后触发,所以我没有得到一条记录,调用加载,然后立即需要采取一些行动进行一系列更新。

由于这是特定于实现的,我在这里会有点抽象,但这是它的要点:

// inside my wrapper for Backbone.Firebase.Collection
this.ready = $.Deferred();

// debounce our ready listener so it fires on the tail end of 
// the initial update clump which reduces the number of update 
// calls on the initial load process considerably
this.readyFn = _.debounce(this.ready.resolve, 250);

// start monitoring for the first series of updates
// this would need to be invoked before the sync is established
this.on( 'add', this.readyFn );

// wait for the data to come in 
this.ready.always( _.bind(function() { 
   // when the ready promise is fulfilled, we can turn off the listener
   this.off('add', this.readyFn);

   // this is where we trigger the listener event used above
   this.trigger('sync');
}, this) );

我小心使用这个解决方案。我发现在大多数情况下,我可以通过忘记初始加载并将所有内容初始化为空来大大简化事情,然后将所有内容视为更新。

我只在需要显示一些替代视图但没有数据的情况下使用它(比如入门说明)。

答案 1 :(得分:1)

这是我想出的一种方法 - 在集合中使用firebase对象:

todos.firebase.on('value', function(snapshot){
    // do stuff
});

这是最好的方法吗?