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

Backbone.js, cannot set context on a callback

本文关键字:回调 设置 上下文 js Backbone      更新时间:2023-09-26

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

  1. 名为AllVenues的父"包装器"模型有一个自定义的提取函数,该函数读取实例化时给定的URL列表
  2. 对于每个URL,它都会创建一个子模型,并对其调用fetch,指定该URL以及一个成功回调
  3. AllVenues实例还有一个属性progress

这就是我遇到的问题。当子模型获取完成时,成功回调没有最初调用它的父模型的上下文。我有点黑了它,因为我可以访问模块,并将父模型存储在变量中,但这对我来说似乎不对。父模型执行了子模型的获取,所以它应该能够以某种方式传递上下文。我不想把参考文献硬编码在里面。

TL;博士

这是我的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();

我认为您误解了_.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是全局的。