如何从Backbone集合和服务器中有选择地删除模型?

时间:2015-03-18 01:26:11

标签: javascript backbone.js

例如,如果要从待办事项列表中删除已完成的待办事项。

从Backbone集合和服务器中有选择地删除模型似乎是一项常见任务。有哪些常见的方法,以及与每种方式相关的成本和收益是什么?

1 个答案:

答案 0 :(得分:1)

解决方案一

var toRemove = collection.filter(function(model) {
  return condition(model);
});
_.invoke(toRemove, 'destroy');

这似乎是最干净的方式。这是Addy used在他的书中删除已完成的待办事项(这是我首先列出此解决方案的一个重要原因)。如果你重复使用过滤功能(就像他一样),它会特别干净。

但是,我认为它比解决方案二慢,因为它涉及collectiontoRemove的迭代,而解决方案二只涉及collection的迭代。尽管如此,它们都有线性运行时间,因此它并不是一件大事。


解决方案二

for (var i = collection.models.length-1; i >= 0; i--) { // looping from back to front
  var model = collection.models[i];
  if (condition(model)) model.destroy();
}

我觉得这个比较干净。如上所述,这样做的好处就是只需要遍历集合,而不是集合+集合的过滤版本。

从后到前循环非常重要。考虑从前到后循环时会发生什么:

for (var i = 0; i < collection.models.length; i++) { // looping from front to back
  var model = this.models[i];
  if (condition(model)) {
    model.destroy();
    i--;
  }
}

当您销毁模型时,collection.models中的模型基本上会向上移动一个。这有两个含义:

  1. 数组的长度减少一个。

  2. 假设你删除了第二个元素。下一个元素将是四个,而不是三个。索引增加到3,并且由于模型向上移动一个,三个索引为2,四个索引为3.

  3. 解决方案:

    1. 在循环的每次迭代后计算collection.models.length。 IE浏览器。 for (var i = 0; i < **collection.models.length**; i++)

    2. 销毁模型后减少i

    3. 你可以从前到后循环,但你只需要处理这些事情,这会使它更复杂。


      解决方案三

      var toRemove = [];
      collection.forEach(function(model) {
        if (condition(model)) toRemove.push(model);
      });
      toRemove.forEach(function(model) {
        model.destroy();
      });
      

      这与Solution One非常相似。

      的差异:

      1. 我们使用forEach来构建toRemove而不是filter

      2. 我们手动迭代并调用destroy而非使用invoke

      3. 与解决方案一一样,您必须遍历collectiontoRemove,因此它可能需要比解决方案二更长的时间。

        注意:我们无法在第一个forEach循环中销毁模型。如果我们这样做,那么它与解决方案二中的前后循环具有相同的问题。要解决此限制,我们必须使用toRemove数组。


        解决方案四

        这会使用reset() + reset事件。

        var toKeep = collection.filter(function(model) {
          return condition(model);
        });
        collection.reset(toKeep);
        

        collection.on('reset', function(after, before) {
          // let after.length = k
          // let before.length = n
          after.sort(); // k*logk
          for (var i = before.length-1; i >= 0; i--) { // n
            var model = before[i];
            if (!binarySearch(model, after)) model.remove(); // logk
          }
          // total runtime: n*logk + k*logk
        });
        

        这对我来说似乎有些过分,但是可以选择。