Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scope issue within Backbone model.fetch() callback (calling setTimeout)

I've a master view (Services) with a collection of child views (Service). Each child view needs to refresh itself every 5 seconds. To do this I had the following [extract]:

Service: Backbone.View.extend({
    ...

    initialize: function () {
        this.model.bind('change', this.render, this);
        _.bindAll(this, 'update');
    },

    render: function () {
        ...
        this.update();
        return this;
    },

    update: function() {
        this.model.fetch();
        setTimeout(this.update, 5000);
    }

    ...

The setTimeout call to update() of course worked as this was correctly bound to the view in question.

The problem comes in when I move setTimeout into the callback for fetch, as this now points to the global scope:

    update: function() {
        this.model.fetch({ success: function() {
            // this is now global
            setTimeout(this.update, 5000);
        }});            
    }

How can I achieve a continous (non-overlapping) update function. Or - how can I apply the view's scope to this inside the fetch callback?

Update

Was just going over this old question, and for future reference I follow this pattern nowadays as I find _.bind OTT here:

    update: function() {
        var self = this;
        this.model.fetch({ success: function() {
            setTimeout(self.update, 5000);
        }});            
    }
like image 358
isNaN1247 Avatar asked Sep 19 '11 08:09

isNaN1247


2 Answers

One of the options is to use Underscore _.bind function:

update: function() {
    this.model.fetch({ success: _.bind(function() {
        setTimeout(this.update, 5000);
    }, this)});            
}
like image 169
kulesa Avatar answered Nov 10 '22 11:11

kulesa


I know this is old question, but the success and failure events return three values: model, response and options. Instead of calling this.update within the success function, you can call model.update:

update: function() {
    this.model.fetch({ success: function( model, response, options) {
       setTimeout(model.update, 5000);
    }});            
}
like image 45
drewloomer Avatar answered Nov 10 '22 11:11

drewloomer