使用正确的方式回调Backbone的fetch方法

12

我的Backbone应用程序有一个名为schedule的视图,我对在成功和错误时调用适当函数的区别有些困惑。我已经尝试了下面列出的两种可能性,但我不知道它们之间有什么区别,以及从位于外部视图中的路由器调用函数的正确方法是什么:

第一种方法:

        require([
            'app/collections/schedule',
            'app/views/schedule'
        ], function(ScheduleCollection, ScheduleView) {

           var scheduleCollection = new ScheduleCollection(),
            scheduleView = new ScheduleView({
                model: scheduleCollection
            });

            scheduleCollection.fetch({
                reset: true,                
                success: function(){
                    scheduleView.successHandler();
                },
                error: function(){
                    scheduleView.errorHandler()
                }
            });
        });

第二种方法

        require([
            'app/collections/schedule',
            'app/views/schedule'
        ], function(ScheduleCollection, ScheduleView) {

           var scheduleCollection = new ScheduleCollection(),
            scheduleView = new ScheduleView({
                model: scheduleCollection
            });

            scheduleCollection.fetch({
                reset: true,                
                success: scheduleView.successHandler(),
                error: scheduleView.errorHandler()                  
            });
        });

在 scheduleView 中

successHandler: function(){
   console.log('success');
}


erroHandler: function(){
   console.log('error');
}
4个回答

17

还有另一种选择:不直接引用视图,而是将集合作为一个参考提供给相关的视图,并监听相关事件。例如,在相关视图中监听集合上的reset事件。如果这不是你想要连接的事件,则从成功/错误回调触发自定义事件,以供你的视图监听。

这里有一个处理重置的示例 - 扩展你的ScheduleView:

var ScheduleView = Backbone.View.extend({ 

    initialize: function () {

        this.listenTo(this.collection, 'reset', this.handleReset);
    },

    handleReset: function () {
        // do whatever you need to do here
    }
};

var scheduleCollection = new ScheduleCollection();
var scheduleView = new ScheduleView({ collection: scheduleCollection });

这是一个关于与集合的成功/错误处理程序绑定的自定义事件示例:
var ScheduleCollection = Backbone.Collection.extend({

    getResults: function () {

        var self = this;

        this.fetch({
            reset: true,
            success: function (collection, response, options) {
                // you can pass additional options to the event you trigger here as well
                self.trigger('successOnFetch');
            },
            error: function (collection, response, options) {
                // you can pass additional options to the event you trigger here as well
                self.trigger('errorOnFetch');
            }
        });
    }
 };

var ScheduleView = Backbone.View.extend({

    initialize: function () {

        this.listenTo(this.collection, 'successOnFetch', this.handleSuccess);
        this.listenTo(this.collection, 'errorOnFetch', this.handleError);
    },

    handleSuccess: function (options) {
        // options will be any options you passed when triggering the custom event
    },

    handleError: function (options) {
        // options will be any options you passed when triggering the custom event
    }
};

var scheduleCollection = new ScheduleCollection();
var scheduleView = new ScheduleView({ collection: scheduleCollection });
scheduleCollection.getResults();

以这种方式进行连接的优点是消除了集合对视图的依赖性。如果您想要多个视图监听发生在您的集合(或集合模型)上的事件,这尤其重要,并且是 Backbone 应用程序的更松散耦合架构。

请提供一个例子。 - ahmedsaber111
太棒了,你详细阐述了这个问题,正是我所需要的! - benjaminz

5
第一种方式是正确的,第二种是错误的。但这种方式最为简洁:
scheduleCollection.fetch({
    reset: true,                
    success: scheduleView.successHandler,
    error: scheduleView.errorHandler
});

尽管从OP中得知,函数scheduleView.successHandler不存在,这可能是一个问题。

你需要将这些方法绑定到 scheduleView 上吗?如果这些方法使用了 this,那么就需要绑定。但在 console.log 的情况下不需要。 - nrabinowitz
@nrabinowitz 是的,我相信是这样... 我从来没有完全清楚过。 - McGarnagle

2
你的第二个例子不起作用的原因是你需要传递一个 函数引用 而不是立即执行它。
var foo = myFunction(); // foo is set to myFunction's return value
var bar = myFunction; // bar is set to a REFERENCE to myFunction

foo === bar // FALSE
bar === myFunction // TRUE

更正后的代码:

scheduleCollection.fetch({
    reset: true,                
    success: scheduleView.successHandler,
    error: scheduleView.errorHandler                  
});

现在,如果你想更加高级地使用,可以使用从返回的XHR对象中获取的jQuery promise API。这种方式优于回调函数,并且再也不需要使用回调函数了。
scheduleCollection.fetch({ reset: true })
    .then(scheduleView.successHandler, scheduleView.errorHandler);

不同之处在于您会得到一个可以传递的承诺...但这是另一篇文章的主题。(无耻地自荐)请查看我关于承诺的三部曲,网址为adamterlson.com


我非常喜欢 Promise 解决方案,代码从左到右读起来非常流畅。我将采用 jQuery Promise 作为我的最佳实践,用于 Backbone 的 fetch 等操作。 - explainer

0
你需要做的是将函数对象分配给“success”和“error”,而不是函数的返回值。 当你这样做时:
function(){...}

它返回一个函数对象,因此 success: function(){...}

是正确的,但如果

a = function(){...}

当你执行a()时,它会执行函数并返回返回值,因此success: a()是错误的,但success: a是正确的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接