Ajax 如何从多个URL填充主干模型
我想使用一个主干模型,它由来自不同URL端点的数据组成。是否可以在一个模型中指定多个URL?我希望避免手动调用AJAX 到目前为止,我一直在使用调用多个URL并将其结果合成为单个对象 到目前为止,我可以想到两种选择:使用每个URL的部分模型构建主干模型,或者使用一个URL,然后覆盖Ajax 如何从多个URL填充主干模型,ajax,backbone.js,Ajax,Backbone.js,我想使用一个主干模型,它由来自不同URL端点的数据组成。是否可以在一个模型中指定多个URL?我希望避免手动调用AJAX 到目前为止,我一直在使用调用多个URL并将其结果合成为单个对象 到目前为止,我可以想到两种选择:使用每个URL的部分模型构建主干模型,或者使用一个URL,然后覆盖model.fetch()调用其他URL。但这两个都让我不舒服 (或者我可以贿赂API开发人员提供一个合并的URL端点…我认为您建议的两种方法都很合理,但就个人而言,我会投票支持获取方法 使用嵌套模型具有“开箱即用”的
model.fetch()
调用其他URL。但这两个都让我不舒服
(或者我可以贿赂API开发人员提供一个合并的URL端点…我认为您建议的两种方法都很合理,但就个人而言,我会投票支持
获取方法
使用嵌套模型具有“开箱即用”的优点;换句话说,通过对每个服务器-客户端映射使用一个模型,您可以避免更改任何主干.model
方法。但是,这种方法的问题在于,最终会导致多个模型的聚集
如果这是有意义的(数据检索除外),那么就坚持使用嵌套模型。但如果不是这样的话,那么您将强制您的代码的其余部分使用多个模型,而不仅仅是一个模型,以保持数据检索代码的简单。如果您希望将数据检索代码复杂化,并使其他所有内容保持简单,那么最好覆盖fetch
fetch
做一件事,那就是通过数据与远程URL之间的一对一映射来检索数据。如果您想要一对多映射,只需覆盖默认的fetch
行为就非常有意义。另外,您知道重写获取
是相当安全的,因为它的名称不是\u fetch
,主干使用下划线样式来命名它的伪私有方法(例如\u validate
)
如果您仍然不喜欢这两种方法中的任何一种,那么还有另一种选择:request
events。最新版本的主干网有一个名为request
的新事件,每当启动fetch
时都会触发该事件。这意味着您可以设置一个事件处理程序来检索辅助数据,以响应主数据的请求,如下所示:
Backbone.Model.extend({
initialize: function() {
this.on('request', this.handleRequest);
_.bindAll(this, 'handleTriggeredResponse');
},
handleRequest: function() {
$.ajax({url: secondDataUrl, complete: this.handleTriggeredResponse});
$.ajax({url: tertiaryDataUrl, complete: this.handleTriggeredResponse});
},
handleTriggeredResponse: function(response) {
this.set(response.data);
},
url: firstDataUrl
});
还有另一个解决办法。使用支持URL数组或哈希的高级jquery ajax执行覆盖默认的Backbone.ajax函数。一旦所有请求完成,它将并行加载数据并将控制权传递回主干模型
ajaxForArray = ->
options = _.first arguments
$.when.apply $, options.url.map (url) ->
$.ajax _.merge _.omit(options, ['url', 'success']), {url}
.done ->
resp =
if options.url.length > 1
_.slice(arguments).map (arg) -> _.first arg
else
_.first arguments
options.success? resp
ajaxForHash = ->
options = _.first arguments
pairs = _.transform options.url, (memo, url, key) ->
memo.push {key, url}
, []
$.when.apply $, pairs.map (pair) ->
$.ajax _.merge _.omit(options, ['url', 'success']), url: pair.url
.done ->
resp = _.slice(arguments).reduce (memo, arg, i) ->
memo[pairs[i].key] = _.first arg
memo
, {}
options.success? resp
Backbone.ajax = ->
options = _.first arguments
if _.isArray options.url
ajaxForArray.apply $, arguments
else if _.isObject(options.url) and not _.isFunction options.url
ajaxForHash.apply $, arguments
else
$.ajax.apply $, arguments
现在可以用URL数组设置模型,如
class ArrayBasedModel extends Backbone.Model
url: ['/aoo', '/boo', '/coo']
parse: (resp) ->
super _.extend {}, resp[0], resp[1], resp[2]
class HashBasedModel extends Backbone.Model
url: {aoo: '/aoo', boo: '/boo', coo: '/coo'}
parse: (resp) ->
super _.extend {}, resp.aoo, resp.boo, resp.coo
或者URL的散列,比如
class ArrayBasedModel extends Backbone.Model
url: ['/aoo', '/boo', '/coo']
parse: (resp) ->
super _.extend {}, resp[0], resp[1], resp[2]
class HashBasedModel extends Backbone.Model
url: {aoo: '/aoo', boo: '/boo', coo: '/coo'}
parse: (resp) ->
super _.extend {}, resp.aoo, resp.boo, resp.coo
因此,当parse()被重写时,只需添加一些合并所有ajax调用结果的基本逻辑,将其传递给Backbone.Model.parse()
在所有这些之后,来自不同URL的属性将在一个模型属性中可用。感谢编辑GammaGames:the(this)
样式过去是完全可行的,但我想下划线已经从它移开了,我的草率的其他修复也得到了赞赏。