4

我正在玩firebase和适得其反。该示例没有明确说明,但我发现当您实例化Backbone.Firebase.Collection. 例如:

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

我怎么知道检索何时完成?

4

2 回答 2

8

在使用 Backfire 的模型进行了相当广泛的工作后,我对此有几个想法。我希望他们中的一些人能为您的项目提供好的想法。

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

首先,摆脱知道“所有数据已加载”的心态,假设这会像我早期一样困扰您。我们现在处于实时环境中。只需从零开始,将每条传入的记录都视为更新。这节省了大量尝试处理状态的时间和精力。

延迟渲染和 DOM 绑定

现在有了 Backbone,我经常发现自己想做一个惰性渲染。也就是说,我想在逻辑上处理以下情况:

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

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

Debounce 作为一种快速而肮脏的解决方案

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();
   }
});

使用 Deferred 等待加载的数据

在我的 Backfire 实现中,我添加了一个有状态的方法,它会在第一次加载时通知我。我使用 jQuery 的Deferred对象做到了这一点。然后我只听集合触发一个sync事件:

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

Firebase 的一个好处是最初的 Firebase.on('child_added'...) 结果(现有记录)往往会出现在一个很好的大块中——一个接一个。所以作为一个额外的好处,我使用 debounce 使我的“加载”方法在初始集群完成后触发,所以我没有得到一条记录,调用加载,然后立即需要对一系列更新采取一些行动。

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

// 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) );

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

我只在不存在数据时需要显示一些替代视图的情况下使用它(例如入门说明)。

于 2013-03-07T16:04:50.957 回答
1

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

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

这是最好的方法吗?

于 2013-03-07T04:30:57.123 回答