2014-10-06 76 views
0

我通常是一個在J2EE(servlet/ejb)框架和庫上工作的後端人。全新的前端,特別是Backbone。因此,這個問題有點小菜一碟。我很感謝任何意見/教程/例子。我會盡可能清楚和詳盡地解釋我的目標/要求。基於來自另一個URL的JSON響應動態地填充集合

這是我第一個SO問題,因此提前打破任何規則道歉。

問:我有一個後端電子商務引擎,它將REST URL作爲產品目錄API的一部分公開。 API 1 -/rest/repository/atg/commerce/catalog/ProductCatalog/product /。 API 1以產品列表作爲單個JSON數組迴應。有趣的是,它只發送每個產品的單獨REST URL。樣品響應:

{"product": [ 
    "http://example.com/rest/repository/atg/commerce/catalog/ProductCatalog/product/prod90004", 
    "http://example.com/rest/repository/atg/commerce/catalog/ProductCatalog/product/prod90005", 
    "http://example.com/rest/repository/atg/commerce/catalog/ProductCatalog/product/prod100027" 
    "http://example.com/rest/repository/atg/commerce/catalog/ProductCatalog/product/prod70011", 
    "http://example.com/rest/repository/atg/commerce/catalog/ProductCatalog/product/prod70013" 
]} 

API 2 - http://example.com/rest/repository/atg/commerce/catalog/ProductCatalog/product/的productId即。 http://example.com/rest/repository/atg/commerce/catalog/ProductCatalog/product/prod90004 從API 1的響應 樣品響應單個產品URL的基本上之一:

{ 
    "dateAvailable": "2000-05-04 15:51:42.521", 
    "displayName": "Warm Black Gloves ", 
    "longDescription": "Protects you from the elements and keeps you looking good, these durable gloves won't let you down.", 
    "repositoryId": "prod90004" 
} 

必需目標:如果API 1返回響應與含有4頁的URL,即4個產品JSON數組,然後我需要顯示的屬性在一個視圖中的4個產品等等。通過對API 2進行4次調用可以檢索屬性;換句話說,向API 1中收到的URL發出4個請求。

問題: 我已經看過一些教程和示例。我無法以某種方式在這個特定用例上得到任何東西。我已經看到的示例假設將會有一個REST API,它將用包含所有模型(本例中爲產品)的JSON數組及其單個JSON響應中的屬性進行響應。但是,這不是這種情況,因爲我必須先調用API 1以獲取產品URL列表,然後調用所有這些URL(在API 1的響應中檢索)以獲取相應模型的屬性。因此,我有點不能夠決定爲如何定義模型,收藏和

我給一個嘗試如下URL屬性等:

(function ($) { 

    var ProductView = Backbone.View.extend({ 

     tagName:"div", 
     className:"bookContainer", 
     template:$("#bookTemplate").html(), 

     render:function() { 
      console.log("inside render of ProductView"); 
      var tmpl = _.template(this.template); 
      this.$el.html(tmpl(this.model.toJSON())); 
      return this; 
     } 
    }); 

    var ProductModel = Backbone.Model.extend({ 

     defaults:{ 
      displayName:"displayName", 
      longDescription:"longDescription", 
      dateAvailable:"dateAvailable", 
      repositoryId:"repositoryId", 
     }, 

     initialize: function(){ 
      this.on("reset", this.renderModelView, this); 
      this.fetch({ 
       reset:true, 
       error:function() { 
        console.log(arguments); 
       } 
      }); 

     }, 

     renderModelView: function(){ 
      var that = this; 
      new ProductView.render({ 
        model: that 
       }); 

     } 
    }); 

    var ProductCollection = Backbone.Collection.extend({ 
     model: ProductModel, 

     initialize: function(){ 
      this.on("reset", this.debugTempfunc, this); 
      this.fetch({ 
       reset:true, 
       error:function() { 
        console.log(arguments); 
       } 
      }); 
     }, 

     debugTempfunc: function(){ 
      console.log("collection length: "+this.length); 
     } 
    }); 

    var ProductURLModel = Backbone.Model.extend({ 

     defaults:{ 
      product: "ProductCatalogProductURLs" 
     }  

    }); 

    var ProductURLCollection = Backbone.Collection.extend({ 
     model: ProductURLModel, 

     url: "http://example.com/rest/repository/atg/commerce/catalog/ProductCatalog/product", 

     initialize: function(){ 
      this.on("reset", this.populateModels, this); 
      this.fetch({ 
       reset:true, 
       error:function() { 
        console.log(arguments); 
       } 
      }); 
     }, 

     populateModels: function(){ 
      var ProductCollectionIns = new ProductCollection(); 

      var that = this; 
      console.log("inside populateModels of ProductURLCollection: "+that); 
      _.each(that.models[0].attributes.product,function(item){ 
       console.log("populateModels, item value: "+item); 
       ProductCollectionIns.url=item; 
       ProductCollectionIns.fetch(); 

      }); 

     }  

    }); 

    var ProductURLCollectionTestIns = new ProductURLCollection(); 

})(jQuery); 

我的計劃是先定義一個ProductURLCollection作爲URL設置爲API 1的URL的集合。該集合將具有單個模型ProductURLModel,其具有n個ProductURLModel(s)... n是在API 1中檢索的URL的數量,其也等同於產品的數量。這表明現在我必須進行n個API 2調用。爲此,我決定創建另一個包含n個ProductModel(s)的集合ProductCollection。

populateModels: function(){ 
      var ProductCollectionIns = new ProductCollection(); 

      var that = this; 
      console.log("inside populateModels of ProductURLCollection: "+that); 
      _.each(that.models[0].attributes.product,function(item){ 
       console.log("populateModels, item value: "+item); 
       ProductCollectionIns.url=item; 
       ProductCollectionIns.fetch(); 

      }); 

     } 

有了這個,我希望我可以從N產品型號(S)動態每次換水ProductCollectionIns網址:ProductCollection的url屬性將在迭代ProductURLCollection模型,如下面的代碼動態設置。但是,我收到「錯誤:一個」url「屬性或函數必須指定」。這是否意味着ProductCollectionIns url屬性未被設置?

我相信在Backbone中必須有一種更簡單的方法來達到上述目的。請任何解決方案或更好的實施,將不勝感激。

+0

您是否在瀏覽器控制檯中檢查了API 1的響應?它顯示了什麼? – booleanhunter 2014-10-06 19:26:03

回答

0

讓我解釋一下Backbone的AJAX系統是如何工作的,首先是Model(但我會在一分鐘內獲得Collection秒)。總之,骨幹網的設計,你要能夠做:

var FooModel = Backbone.Model.extend({url: 'www.example.com'}); 

var someModel = new FooModel({id: 5}); 
someModel.fetch().done(function() { 
    // Now someModel should be populated with the AJAX data for model #5 
}); 

在幕後發生的事情還有,當你調用fetch骨幹查找具有Model相關的URL。由於您從未定義過一個(或者是urlRoot),因此您會收到您遇到的錯誤,因爲Backbone不知道在哪裏進行AJAX調用。

一旦您通過url屬性告訴Backbone在哪裏可以找到該類型型號的數據,Backbone將撥打'www.example.com/5'(因爲該型號的id爲5)。然後將主幹期望URL返回,看起來像一個響應:

{id: 1, someAttribute: 2, someOtherAttribute: 'spam'} 

這JSON將成爲someModel的屬性,所以你可以做:

someModel.get('someAttribute'); // == 2 

Collection的工作幾乎相同的方式,不同的是它們期望的JSON響應:

[{id: 1, someAttribute: 2, someOtherAttribute: 'spam'}, 
{id: 2, someAttribute: 55, someOtherAttribute: 'eggs'}] 

和它們返回的數組中的每個成員在轉換到一個Model

正如你猜測的那樣,有一種比你的populateModels方法更簡單的方法:如果你只是按照我描述的模式,你的集合應該自動創建模型,無需額外的努力。如果您確實需要定製某些東西(例如,您想將服務器中的「foo」屬性更改爲「bar」屬性),則可以覆蓋ModelCollectionparse方法,該方法將「原始的「AJAX數據並返回您的轉換版本:

var someModel = new FooModel({ 
    id: 5, 
    parse: function(raw) { 
     raw.bar = raw.foo; 
     delete raw.foo; 
     return raw; 
    } 
}); 

希望有所幫助。

相關問題