【问题标题】:Backbone multiple collections fetch from a single big JSON file从单个大 JSON 文件中获取主干多个集合
【发布时间】:2012-03-20 03:48:21
【问题描述】:

我想知道是否有更好的方法来创建从单个大 JSON 文件中获取的多个集合。我得到一个 JSON 文件,看起来像这样。

{
  "Languages": [...],
  "ProductTypes": [...],
  "Menus": [...],
  "Submenus": [...],
  "SampleOne": [...],
  "SampleTwo": [...],
  "SampleMore": [...]
}

我正在使用 url/fetch 为上述 JSON 的每个节点创建每个集合。

var source = 'data/sample.json'; 

Languages.url = source;
Languages.fetch();

ProductTypes.url = source;
ProductTypes.fetch();

Menus.url = source;
Menus.fetch();

Submenus.url = source;
Submenus.fetch();

SampleOne.url = source;
SampleOne.fetch();

SampleTwo.url = source;
SampleTwo.fetch();

SampleMore.url = source;
SampleMore.fetch();

有什么更好的解决方案吗?

【问题讨论】:

    标签: json backbone.js


    【解决方案1】:

    Backbone 非常适合您的应用程序适合它提供的模式。但是,当它对您的应用程序有意义时,不要害怕绕过它。这是一个很小的图书馆。仅仅为了适应主干网的模式而重复和重复的 GET 请求可能效率非常低。查看jQuery.getJSON 或您最喜欢的基本 AJAX 库,以及一些基本元编程,如下所示:

    //Put your real collection constructors here. Just examples.
    var collections = {
        Languages: Backbone.Collection.extend(),
        ProductTypes: Backbone.Collection.extend(),
        Menus: Backbone.Collection.extend()
    };
    
    function fetch() {
        $.getJSON("/url/to/your/big.json", {
            success: function (response) {
                for (var name in collections) {
                    //Grab the list of raw json objects by name out of the response
                    //pass it to your collection's constructor
                    //and store a reference to your now-populated collection instance
                    //in your collection lookup object
                    collections[name] = new collections[name](response[name]);
                }
            }
        });
    }
    
    fetch();
    

    调用fetch() 并且异步回调完成后,您可以执行collections.Menus.at(0) 之类的操作来获取已加载的模型实例。

    【讨论】:

      【解决方案2】:

      您当前的方法除了很长之外,还存在多次检索大文件的风险(浏览器缓存在此处并不总是有效,尤其是在您发出下一个请求时第一个请求尚未完成的情况下)。

      我认为这里最简单的选择是直接使用 jQuery,而不是 Backbone,然后在您的集合上使用 .reset()

      $.get('data/sample.json', function(data) {
          Languages.reset(data['Languages']);
          ProductTypes.reset(data['ProductTypes']);
          // etc
      });
      

      如果您想减少冗余代码,您可以将您的集合放入 app 之类的命名空间中,然后执行以下操作(虽然它可能有点太聪明以至于难以辨认):

      app.Languages = new LanguageCollection();
      // etc
      
      $.get('data/sample.json', function(data) {
          _(['Languages', 'ProductTypes', ... ]).each(function(collection) {
              app[collection].reset(data[collection]);
          })
      });
      

      【讨论】:

        【解决方案3】:

        我认为您可以解决您的需求并且仍然保持在 Backbone 范式中,我认为适合我的优雅解决方案是创建一个 Modelfetch 大 JSON 并将其用于fetch 在其change 事件中的所有Collections

        var App = Backbone.Model.extend({
          url: "http://myserver.com/data/sample.json",
        
          initialize: function( opts ){
            this.languages    = new Languages();
            this.productTypes = new ProductTypes();
            // ...
        
            this.on( "change", this.fetchCollections, this );
          },
        
          fetchCollections: function(){
            this.languages.reset( this.get( "Languages" ) );
            this.productTypes.reset( this.get( "ProductTypes" ) );
            // ...
          }
        });
        
        var myApp = new App();
        myApp.fetch();
        

        您可以通过以下方式访问您的所有收藏:

        myApp.languages
        myApp.productTypes
        ...
        

        【讨论】:

        • 虽然模型抽象很吸引人,但我不喜欢这种方法。数据永远不会存储在它的当前结构中......它将被分成不同的集合。您不妨只使用 .json()。模型的目的是存储“东西”对吗?
        【解决方案4】:

        您可以使用 parse 方法轻松完成此操作。设置一个模型并为每个集合创建一个属性。没有什么说你的模型属性必须是一个单一的数据,不能是一个集合。

        当您运行 fetch 时,它会将整个响应返回到 parse 方法,您可以通过在模型中创建 parse 函数来覆盖该方法。类似的东西:

        parse: function(response) {
            var myResponse = {};
            _.each(response.data, function(value, key) {
                myResponse[key] = new Backbone.Collection(value);
            }
        
            return myResponse;
        }
        

        如果您不想将它们包含在模型中,也可以在全局级别或其他命名空间中创建新集合,但这取决于您。

        稍后要从模型中获取它们,您只需执行以下操作:

        model.get('Languages');
        

        【讨论】:

        • 我们的服务器在解析时为我提供了大量嵌套的对象,并根据需要添加到集合中。
        【解决方案5】:

        backbone-relational 在主干中提供了一个解决方案(不使用 jQuery.getJSON),如果您已经在使用它,这可能是有意义的。 https://stackoverflow.com/a/11095675/70987 的简短回答,如果需要,我很乐意详细说明。

        【讨论】:

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