将主干集合与服务器响应合并

发布于 2024-12-16 23:53:51 字数 1584 浏览 0 评论 0原文

TL;DR:如果我从服务器轮询整个模型集合,如何将更改的属性合并到每个模型中,并从集合中添加/删除添加/删除的模型?

在我的主干应用程序中,我正在轮询整个模型集合。我有一个 Backbone.Collection ,每次获取模型数组时我基本上都会调用 reset ,所以:

myCollection.reset(server_response);

唯一的问题是它摆脱了旧模型,有点消除了事件对模型的好处。这当然是reset的目的,但我想做的只是修改模型的更改属性,并删除不在响应中的模型,并添加在响应中但不在响应中的模型集合。

本质上,我想要对数据进行某种合并

对于已经在响应和集合中的模型,我相信我可以执行 model.set(attributes) ,并且它只负责设置那些实际上发生了变化,触发了流程中的 change 事件。这太棒了。

但是,如何处理模型在响应中但不在集合中的情况,反之亦然,不在响应中但在集合中?

我提出的解决方案

我不知道骨干是否已经有办法做到这一点,我可能过于复杂,这就是我问的原因,但我当时正在考虑在我的集合上创建一种方法它通过server_response

它将获取 server_response 的所有 id 属性,以及集合中已有模型的所有 id 属性。

响应中 id 的差异 - 集合 = 添加模型,反之亦然将删除模型。分别从集合中添加和删除这些模型。

两组 id 的交集将是修改后的模型,因此迭代这些 id 并简单地执行 collection.get(id)。设置(属性)

在伪咖啡脚本中:

merge: (server_response) =>
  response_ids = _.pluck(server_response, 'id')
  collection_ids = @pluck('id')

  added = _.difference(response_ids, collection_ids)

  for add in added
    @add(_.find(server_response, (model) ->
      return model.id == add
    ))

  removed = _.difference(collection_ids, response_ids)

  for remove in removed
    @remove(@get(remove))

  changed = _.intersection(response_ids, collection_ids)

  for change in changed
    @get(change).set(_.find(server_response, (model) ->
      return model.id == change
    ))

TL;DR: If I'm polling the entire collection of models from the server, how can I merge the changed attributes into each model and add/remove added/removed models from the collection?

In my backbone app, I am polling for the entire collection of models. I have a Backbone.Collection that I am basically calling reset on each time I get the array of models, so:

myCollection.reset(server_response);

The only problem with this is that it gets rid of the old models, kind of eliminating the benefit of events on a model. This is reset's purpose of course, but what I want to do is only modify the changed attributes of the models, and remove models not in the response, and add models that were in the response but not the collection.

Essentially I want a sort of merge of the data.

For models that are in the response and in the collection already, I believe I can just do model.set(attributes) and it takes care of seting only the ones that actually changed, triggering the change events in the process. This is great.

But how do I handle the cases where the models were in the response but not in the collection already, and vice versa, not in the response but in the collection?

My Proposed Solution

I don't know if backbone already has a way of doing this, and I may be overcomplicating which is why I'm asking, but I was thinking then of creating a method on my collection which gets passed the server_response.

It would get all of the id attributes of the server_response, and all of the id attributes of the models already in the collection.

The difference of the id's in response - collection would = added models, and vice versa would be removed models. Add and remove those models respectively from the collection.

The intersection of both sets of id's would be the modified models, so iterate through these id's and simply do a collection.get(id).set(attributes).

In pseudocoffeescript:

merge: (server_response) =>
  response_ids = _.pluck(server_response, 'id')
  collection_ids = @pluck('id')

  added = _.difference(response_ids, collection_ids)

  for add in added
    @add(_.find(server_response, (model) ->
      return model.id == add
    ))

  removed = _.difference(collection_ids, response_ids)

  for remove in removed
    @remove(@get(remove))

  changed = _.intersection(response_ids, collection_ids)

  for change in changed
    @get(change).set(_.find(server_response, (model) ->
      return model.id == change
    ))

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦幻之岛 2024-12-23 23:53:51

这种技术有时很有用。我们使用以下方法扩展 Collection。这应该可以满足您的要求。它不在咖啡中,但您可以轻松移植它。享受!

// Take an array of raw objects
// If the ID matches a model in the collection, set that model
// If the ID is not found in the collection, add it
// If a model in the collection is no longer available, remove it
freshen: function (objects) {
    var model;
    // Mark all for removal

    this.each(function (m) {
        m._remove = true;
    });

    // Apply each object
    _(objects).each(function (attrs) {
        model = this.get(attrs.id);
        if (model) {
            model.set(attrs); // existing model
            delete model._remove
        } else {
            this.add(attrs); // new model
        }
    }, this);

    // Now check for any that are still marked for removal
    var toRemove = this.filter(function (m) {
        return m._remove;
    })

    _(toRemove).each(function (m) {
        this.remove(m);
    }, this);
    this.trigger('freshen', this);
}

This technique is useful sometimes. We extend Collection with the following method. This should do what you're looking for. It's not in coffee, but you could easily port it. Enjoy!

// Take an array of raw objects
// If the ID matches a model in the collection, set that model
// If the ID is not found in the collection, add it
// If a model in the collection is no longer available, remove it
freshen: function (objects) {
    var model;
    // Mark all for removal

    this.each(function (m) {
        m._remove = true;
    });

    // Apply each object
    _(objects).each(function (attrs) {
        model = this.get(attrs.id);
        if (model) {
            model.set(attrs); // existing model
            delete model._remove
        } else {
            this.add(attrs); // new model
        }
    }, this);

    // Now check for any that are still marked for removal
    var toRemove = this.filter(function (m) {
        return m._remove;
    })

    _(toRemove).each(function (m) {
        this.remove(m);
    }, this);
    this.trigger('freshen', this);
}
热情消退 2024-12-23 23:53:51

这三天前刚刚进入 Backbone master:

https://github.com/documentcloud/backbone/pull/1220

This just went into Backbone master 3 days ago:

https://github.com/documentcloud/backbone/pull/1220

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文