【问题标题】:backbone.js - getting extra data along with the request主干.js - 随请求获取额外数据
【发布时间】:2011-04-19 03:20:16
【问题描述】:

我有一个包含一些用户的集合。需要的一些信息是总共有多少,有多少页等。我如何将这些传回给客户?或者他们是否必须来自一个单独的视图,在这种情况下我需要多个 ajax 调用?我想拥有fetch() 的集合,并且还想收到一些这样的“元数据”。有什么好的处理方法?

【问题讨论】:

  • 您能提供更多信息吗?你的服务器是什么样的?您需要支持哪些浏览器?您多久获取一次数据?
  • @tjameson 我的服务器只是使用 php 的 nginx。我不需要支持任何特定的浏览器(如果我愿意,我可以只支持 chrome 和 firefox)。我比较频繁地获取我的数据(这只是简单的操作),因此更改页码或进行快速搜索等。

标签: javascript jquery ajax backbone.js underscore.js


【解决方案1】:

一般情况下,您需要在集合类的 parse 方法中处理这个问题。它的职责是接受响应并返回一组模型属性。但是,如果您不介意 parse 方法有这个额外的责任,您可以做更多的事情。

UserList = Backbone.Collection.extend({

    model: User,

    url: '/users',

    parse: function(data) {
        if (!data) {
            this.registered_users = 0;
            return [];
        }
        this.registered_users = data.registered_users;
        var users = _(data.users).map(
            function(user_data) {
                var user = {};
                user['name'] = user_data.name;
                return user;
            }
        );
        return users;
    }
});

所以在上面的简单例子中,假设服务器返回一个包含注册用户计数和用户属性数组的响应。您将解析并返回用户属性,然后选择注册用户数并将其设置为模型上的变量。
parse 方法将作为 fetch 的一部分被调用。所以不需要修改 fetch,直接使用自带的 hook 方法即可。

纯粹主义者会说你给了 parse 方法一个次要的责任,这可能会让一些人感到惊讶(例如,返回一些东西和修改模型状态)。不过,我觉得还可以。

【讨论】:

    【解决方案2】:

    执行此操作的一种方法是覆盖 Collection::fetch() 方法,以便它从响应中解析此元数据。您可以让后端返回如下响应:

    {
        "collection": [
            { ... model 1 ... },
            { ... model 2 ... },
            ...
        ],
        "total_rows": 98765,
        "pages":      43
    }
    

    在覆盖原始Backbone.Collection::fetch() 方法的fetch 方法中,您可以分别处理对象的每个属性。这是您可以使用稍微修改的fetch 方法进行覆盖:

    _.extend(Backbone.Collection.prototype, {
      fetch : function(options) {
        options || (options = {});
        var collection = this;
        var success = options.success;
        options.success = function(resp) {
          // Capture metadata
          if (resp.total_rows) collection.total_rows = resp.total_rows;
          if (resp.pages)      collection.pages      = resp.pages;
    
          // Capture actual model data
          collection[options.add ? 'add' : 'refresh'](
            collection.parse(resp.collection), options);
    
          // Call success callback if necessary
          if (success) success(collection, resp);
        };
        options.error = wrapError(options.error, collection, options);
        (this.sync || Backbone.sync).call(this, 'read', this, options);
        return this;
    });
    

    请注意,这种使用_.extend 的方法将影响所有您扩展Backbone.Collection 的类。

    这样,您不必对后端进行 2 次单独调用。

    【讨论】:

    • 我不认为重写框架方法是解决这个问题的正确方法。相反,您希望生活在钩子方法中以完成所要求的内容。 Parse 似乎是这种事情的一个合适的地方。覆盖框架方法会带来危险,当您想要升级backbone.js 时,事情可能无法按预期工作,或者您可能无法利用已分配给该方法的任何新功能。
    • 你是对的,通常你不想影响从框架原型继承的所有方法。出于某种原因,我认为 OP 希望在所有 Collection 类上都具有此功能,并且覆盖框架方法是一种方便的方法。无论如何,parse 方法似乎确实是一个更好的地方。
    【解决方案3】:

    我会在页面创建时引导信息。服务器创建站点时将信息写入 html 文档。像这样,您根本不必进行 ajax 调用。我对整个集合执行此操作,以免先加载页面,然后等待 ajax 调用返回所需的信息。

    Python 代码示例:

    第 64 行:https://github.com/ichbinadrian/maps/blob/master/python/main.py

    第 43 行:https://github.com/ichbinadrian/maps/blob/master/templates/index.html

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多