2015-07-28 74 views
7

我有一個場景,其中fetch()調用模型將返回一個屬性需要傳遞給另一個API的數據,並且該API中的返回類型將是實際需要的數據。骨幹模型:解析覆蓋中的Ajax請求

var Issue = Backbone.Model.extend({ 
    urlRoot: 'https://api.github.com/repos/ibrahim-islam/ibrahim-islam.github.io/issues', 
    parse: function(response, options){ 
     var markdown = new Markdown({ text : response.body }); 
     markdown.fetch({ 
      contentType: 'application/json', 
      type: 'POST', 
      data: JSON.stringify(markdown.toJSON()), 
      success: function(data){ 
       response.body = data; 
      } 
     }); 
     return response; 
    } 
}); 

var Markdown = Backbone.Model.extend({ 
    defaults:{ 
     'text': '', 
     'mode' : 'markdown' 
    }, 
    url: 'https://api.github.com/markdown' 
}); 

所以,當Issue將獲取:

var issue = new Issue({id: 1}); 
issue.fetch().then(function(){ 
    //do stuff 
}); 

它將擁有這反過來我需要傳遞給另一個API並獲得該響應的含降價語法文字body一個屬性,該屬性會傳下來查看。

從上面可以看出,我試圖覆蓋parse,但它的返回類型必須是一個對象,並且fetch將是async所以我可以在這裏做什麼來使這個工作?

注:我知道在服務器中彙總數據,然後接收它將是最好的主意,但這是不可能的atm。

+0

'JSON.stringify(markdown.toJSON())' - 這將是雙編碼,你確定要嗎? – Tomalak

+0

@Tomalak只有在我的請求完成之後。但我會再試一次。感謝您的提醒。 – lbrahim

回答

4

您可以覆蓋Issue模型中的sync method來鏈接您的請求。

var Issue = Backbone.Model.extend({ 
    urlRoot: 'https://api.github.com/repos/ibrahim-islam/ibrahim-islam.github.io/issues', 

    sync: function(method, model, options) { 
     if (method !== 'read') 
      return Backbone.sync.apply(this, arguments); 

     // first request 
     var xhr = Backbone.ajax({ 
      type: 'GET', 
      dataType: 'json', 
      url: _.result(model, 'url') 
     }); 

     // second request 
     return xhr.then(function (resp1) { 
      var markdown = new Markdown({text : resp1.body || 'body'}); 
      var data = markdown.toJSON(); 

      // the callback to fill your model, will call parse 
      var success = options.success; 

      return Backbone.ajax({ 
       url: _.result(markdown, 'url'), 
       dataType: 'html', 
       contentType: 'application/json', 
       type: 'POST', 
       data: data 
      }).then(function(resp2) { 
       // sets the data you need from the response 
       var resp = _.extend({}, resp1, { 
        body: resp2 
       }); 

       // fills the model and triggers the sync event 
       success(resp); 

       // transformed value returned by the promise 
       return resp; 
      }); 
     }); 
    } 
}); 

的選項哈希傳遞給Model.sync包含回調model.parse,你可以用它來設置你的模型的屬性,當你滿意你的數據。

並演示http://jsfiddle.net/puwueqe3/5/

+0

這似乎比我的建議更好。從我+1。 – ivarni

+0

@nikoshr我需要主對象和markdown解析結果,以便我可以替換'body'屬性。請看這個小提琴:http:// jsfiddle。net/ibrahimislam/puwueqe3/2/ – lbrahim

+1

@lbrahim我以某種方式錯過了第二個請求返回HTML而不是JSON。更新 – nikoshr

2

我認爲你將不得不重寫模型fetch來得到這個工作

考慮一下的默認獲取的樣子:

fetch: function(options) { 
    options = _.extend({parse: true}, options); 
    var model = this; 
    var success = options.success; 
    options.success = function(resp) { 
    var serverAttrs = options.parse ? model.parse(resp, options) : resp; 
    if (!model.set(serverAttrs, options)) return false; 
    if (success) success.call(options.context, model, resp, options); 
    model.trigger('sync', model, resp, options); 
    }; 
    wrapError(this, options); 
    return this.sync('read', this, options); 
}, 

github

該實現不支持異步版本爲model.parse,但由於您使用.extend創建了模型類,因此您可以使用自己的實現覆蓋此類,以便查看它的功能。它需要一個options對象,創建一個success回調,然後委託給Backbone.Sync

這就是那個調用parse的回調,這就是需要支持異步的東西。

做到這一點最快,最骯髒的方法可能是複製和修改現有的默認提取。

var MyModel = Backbone.Model.extend({ 

    fetch: function(options) { 
     options = _.extend({parse: true}, options); 
     var model = this; 
     var success = options.success; 
     options.success = function(resp) { 

     function parser(resp, options, cb) { 
      ...do your async request stuff and call cb with the result when done... 
     } 

     parser(resp, options, function(result) { 
      if (!model.set(result, options)) return false; 
      if (success) success.call(options.context, model, resp, options); 
      model.trigger('sync', model, resp, options); 
     }); 

     }; 
     wrapError(this, options); 
     return this.sync('read', this, options); 
    } 

}); 

這只是你如何嘗試解決這個問題的一個例子。我沒有測試過它,它可能無法正常工作,但我沒有看到任何明顯的原因,爲什麼它不應該。