Search code examples
javascriptclosuresgoogle-closure-compilergoogle-closuregoogle-closure-library

Google Closure: Passing 'this' into window.setInterval


I have a model js file which looks like

goog.provide('model.ErrorLogger');
/**
 * @constructor
 */
model.ErrorLogger = function() {
    window.onerror = goog.bind(this.errorHandler, this);
    this.doInitialSend();

};
goog.addSingletonGetter(model.ErrorLogger);

model.ErrorLogger.prototype.ws_ErrLgr_config = true;

model.ErrorLogger.prototype.doInitialSend = function(){
    if (this.ws_ErrLgr_config){
        window.setInterval(this.sendReport, this.ws_ErrLgr_config);
    }   

};

model.ErrorLogger.prototype.sendReport = function(){
    // the value of 'this' needs to be of the ErrorLogger model and not windows
    if (!this.ws_ErrLgr_config || this.stopped) {
          //some more code here
    }
}

In the constructor I call the doInitialSend function which set the window.setInterval. Now in the sendReport function the the value of 'this' is not correct. How to correctly pass 'this' to get the correct value instead of getting window's this. I tried storing the the value of this in a reference but that didn't work either. For example

var that = this;
window.setInterval(that.sendReport, that.ws_ErrLgr_config);

Solution

  • The idiomatic way to do this in Google Closure is using goog.bind, with the advantage that it's guaranteed it's always going to work. Plus it will use Function.prototype.bind() under the hood when that is available.

    In that case the solution will be:

    myIntervalInMilliseconds = 1000; // One second.
    window.setInterval(goog.bind(this.sendReport, this), myIntervalInMilliseconds);
    

    Using that = this works, but requires you to explicitly wrap your function within another one to capture that as this within the desired function.

    It's much better using Function.prototype.bind() for that, as pointed out in the other answers. However this won't work if you care to support older browsers (IE < 9).


    PS: Another issue in your code is that it is using this.ws_ErrLgr_config as the interval, which is set to true in the prototype. This is incorrect, you should pick a number to represent your interval.