Backbone.js,无法在回调上设置上下文

时间:2013-08-11 05:49:08

标签: javascript backbone.js marionette

好的,所以我正在研究一种方法来覆盖模型上的fetch方法。我希望能够传递一个URL列表并让它对每个URL进行获取,对结果应用一些处理,然后在它们全部完成后更新自己的属性。这是基本设计:

  1. 名为 AllVenues 的父“包装器”模型具有自定义提取功能,该功能读取实例化时给出的URL列表
  2. 对于每个URL,它会创建一个子模型,并在其上调用fetch,指定该URL以及成功回调。
  3. AllVenues 实例还有一个属性 progress ,它需要在成功回调中更新,以便知道所有Child fetch的完成时间。
  4. 这就是我遇到问题的部分。当子模型提取完成时,成功回调没有最初调用它的父模型的上下文。我有点攻击它,因为我可以访问模块并将父模型存储在变量中,但这对我来说似乎不对。父模型执行了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();
    

1 个答案:

答案 0 :(得分: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);

另请注意,我添加了一个丢失的var,可能您不希望successCallback为全局。