1

Ok, so I am working on a method to override the fetch method on a model. I want to be able to pass it a list of URL's and have it do a fetch on each one, apply some processing to the results, then update its own attributes when they have all completed. Here's the basic design:

  1. A Parent "wrapper" Model called AllVenues has a custom fetch function which reads a list of URL's it is given when it is instantiated
  2. For each URL, it creates a Child Model and calls fetch on it specifying that URL as well as a success callback.
  3. The AllVenues instance also has a property progress which it needs to update inside the success callback, so that it will know when all Child fetch's are complete.

And that's the part I'm having problems with. When the Child Model fetch completes, the success callback has no context of the Parent Model which originally called it. I've kind of hacked it because I have access to the Module and have stored the Parent Model in a variable, but this doesn't seem right to me. The Parent Model executed the Child's fetch so it should be able to pass the context along somehow. I don't want to hardcode the reference in there.

TL;DR

Here's my jsFiddle illustrating the problem. The interesting part starts on line 13. http://jsfiddle.net/tonicboy/64XpZ/5/

The full code:

// 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();
4

1 回答 1

3

我认为你误解了它的_.bind工作原理。_.bind返回绑定函数,它不会就地修改它。事实上,文档可能会更清楚一点。

所以这:

_.bind(successCallback, this);

毫无意义,因为您忽略了_.bind返回的绑定函数。我想你想说的是:

var successCallback = _.bind(function(model) {
    console.log("Returning from the fetch for a model");
    Mod.controller.model.join(model);
}, this);

另请注意,我添加了一个 missing var,大概您不想successCallback成为全球性的。

于 2013-08-11T06:01:32.940 回答