Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

scope when doing OO javascript callbacks

Folks - I'm trying to learn how to write OO Javascript, I come from as3 OO background... issue I'm having is with passing a class' method as a callback to another class...

in the example below, i create an instance of AppController class, and in it, i create an instance of ConnectionMonitor class. I pass one of AppController's methods to be called back by ConnectionMonitor. The calling back works fine, but seems that what's inside the callback function looses the scope of the class its in (AppController )...

any thoughts?

//in the HTML
<script>
    $(document).ready( function(){
        new AppContoller().init();
    });
</script>


//in the js file

//AppController Class
var AppContoller = function(){
    this.body = $("body");

    this.init = function(){
        this.connection = new ConnectionMonitor();
        this.connection.detectInitialConnection( this.initialConnectionDetected );
    }

    //callback function I pass
    this.initialConnectionDetected = function(bool){
        if(bool){
            trace("app connected? "+bool); // logs - "app connected? true"
            this.showOnlineSwf();  //thows error - "Object [object DOMWindow] has no method 'showOnline' "
        }
        else{

        }
    }

    this.showOnlineSwf = function(){
        trace("i'm online");

    }

}

//ConnectionMonitor Class
var ConnectionMonitor = function()
{   
    this.detectInitialConnection = function(callbackFunction){
        setTimeout(callbackFunction, 1000, [true]);
    }
}




function trace(arg){
    console.log(arg.toString());
}
like image 847
nuway Avatar asked Nov 28 '25 17:11

nuway


1 Answers

Modify init to bind the callback to the original context:

this.init = function() {
    this.connection.detectInitialConnection(
        this.initialConnectionDetected.bind(this));
}

Unfortunately, bind is not supported in all browsers, but you can capture the current value of this in a closure to achieve a similar effect:

this.init = function() {
    var that = this;
    this.connection.detectInitialConnection(function(detected) {
        that.initialConnectionDetected(detected);
    });
}

Yet another approach is to make detectInitialConnection capable of handling an optional context parameter:

this.detectInitialConnection = function(callbackFunction, _this){
    setTimeout(function() {
        callbackFunction.apply(_this || this, arguments);
    }, 1000, [true]);
}

You'd then call it like this:

this.init = function() {
    this.connection.detectInitialConnection(
        this.initialConnectionDetected, this);
}

The point in each of these examples is to retain a reference to the value of this from the context in which detectInitialConnection was called.

like image 179
Wayne Avatar answered Nov 30 '25 05:11

Wayne



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!