わかりましたので、モデルの fetch メソッドをオーバーライドするメソッドに取り組んでいます。URL のリストを渡して、それぞれをフェッチし、結果に何らかの処理を適用し、すべてが完了したら独自の属性を更新できるようにしたいと考えています。基本的な設計は次のとおりです。
- AllVenuesと呼ばれる親の「ラッパー」モデルには、インスタンス化されたときに指定された URL のリストを読み取るカスタム fetch 関数があります。
- URL ごとに子モデルを作成し、その URL と成功のコールバックを指定して fetch を呼び出します。
- AllVenuesインスタンスには、成功のコールバック内で更新する必要があるプロパティprogressもあります。これにより、すべての Child fetch がいつ完了したかがわかります。
そして、それは私が問題を抱えている部分です。子モデルのフェッチが完了すると、成功のコールバックには、最初にそれを呼び出した親モデルのコンテキストがありません。モジュールにアクセスでき、親モデルを変数に保存しているので、ちょっとハックしましたが、これは私には正しくないようです。親モデルは子のフェッチを実行したので、何らかの方法でコンテキストを渡すことができるはずです。そこに参照をハードコーディングしたくありません。
TL;DR
これが問題を示す私のjsFiddleです。興味深い部分は 13 行目から始まります。http://jsfiddle.net/tonicboy/64XpZ/5/
完全なコード:
// Define the app and a region to show content
// -------------------------------------------
var App = new Marionette.Application();
App.addRegions({
"mainRegion": "#main"
});
App.module("SampleModule", function (Mod, App, Backbone, Marionette, $, _) {
var MainView = Marionette.ItemView.extend({
template: "#sample-template"
});
var AllVenues = Backbone.Model.extend({
progress: 0,
join: function (model) {
this.progress++;
// do some processing of each model
if (this.progress === this.urls.length) this.finish();
},
finish: function() {
// do something when all models have completed
this.progress = 0;
console.log("FINISHED!");
},
fetch: function() {
successCallback = function(model) {
console.log("Returning from the fetch for a model");
Mod.controller.model.join(model);
};
_.bind(successCallback, this);
$.each(this.urls, function(key, val) {
var venue = new Backbone.Model();
venue.url = val;
venue.fetch({
success: successCallback
});
});
}
});
var Venue = Backbone.Model.extend({
toJSON: function () {
return _.clone(this.attributes.response);
}
});
var Controller = Marionette.Controller.extend({
initialize: function (options) {
this.region = options.region;
this.model = options.model;
this.listenTo(this.model, 'change', this.renderRegion);
},
show: function () {
this.model.fetch();
},
renderRegion: function () {
var view = new MainView({
model: this.model
});
this.region.show(view);
}
});
Mod.addInitializer(function () {
var allVenues = new AllVenues();
allVenues.urls = [
'https://api.foursquare.com/v2/venues/4a27485af964a52071911fe3?oauth_token=EWTYUCTSZDBOVTYZQ3Z01E54HMDYEPZMWOC0AKLVFRBIEXV4&v=20130811',
'https://api.foursquare.com/v2/venues/4afc4d3bf964a520512122e3?oauth_token=EWTYUCTSZDBOVTYZQ3Z01E54HMDYEPZMWOC0AKLVFRBIEXV4&v=20130811',
'https://api.foursquare.com/v2/venues/49cfde17f964a520d85a1fe3?oauth_token=EWTYUCTSZDBOVTYZQ3Z01E54HMDYEPZMWOC0AKLVFRBIEXV4&v=20130811'
];
Mod.controller = new Controller({
region: App.mainRegion,
model: allVenues
});
Mod.controller.show();
});
});
App.start();