Help needed with Javascript Variable Scope / OOP and Call Back Functions

Posted by gargantaun on Stack Overflow See other posts from Stack Overflow or by gargantaun
Published on 2010-05-18T09:45:12Z Indexed on 2010/05/18 10:00 UTC
Read the original article Hit count: 334

Filed under:
|
|

I think this issue goes beyond typical variable scope and closure stuff, or maybe I'm an idiot. Here goes anyway...

I'm creating a bunch of objects on the fly in a jQuery plugin. The object look something like this

function WedgePath(canvas){
    this.targetCanvas = canvas;
    this.label;
    this.logLabel = function(){ console.log(this.label) }
}

the jQuery plugin looks something like this

(function($) {
  $.fn.myPlugin = function() {

  return $(this).each(function() {

        // Create Wedge Objects
        for(var i = 1; i <= 30; i++){ 
            var newWedge = new WedgePath(canvas);
            newWedge.label = "my_wedge_"+i;
            globalFunction(i, newWedge]);
        } 
    });
  }
})(jQuery);

So... the plugin creates a bunch of wedgeObjects, then calls 'globalFunction' for each one, passing in the latest WedgePath instance. Global function looks like this.

function globalFunction(indicator_id, pWedge){

    var targetWedge = pWedge;   
    targetWedge.logLabel();

}

What happens next is that the console logs each wedges label correctly. However, I need a bit more complexity inside globalFunction. So it actually looks like this...

function globalFunction(indicator_id, pWedge){

        var targetWedge = pWedge;   

        someSql = "SELECT * FROM myTable WHERE id = ?";
        dbInterface.executeSql(someSql, [indicator_id], function(transaction, result){

            targetWedge.logLabel();

        })

    }

There's a lot going on here so i'll explain. I'm using client side database storage (WebSQL i call it). 'dbInterface' an instance of a simple javascript object I created which handles the basics of interacting with a client side database [shown at the end of this question]. the executeSql method takes up to 4 arguments

  • The SQL String
  • an optional arguments array
  • an optional onSuccess handler
  • an optional onError handler (not used in this example)

What I need to happen is: When the WebSQL query has completed, it takes some of that data and manipulates some attribute of a particular wedge. But, when I call 'logLabel' on an instance of WedgePath inside the onSuccess handler, I get the label of the very last instance of WedgePath that was created way back in the plugin code.

Now I suspect that the problem lies in the var newWedge = new WedgePath(canvas); line. So I tried pushing each newWedge into an array, which I thought would prevent that line from replacing or overwriting the WedgePath instance at every iteration...

wedgeArray = [];

// Inside the plugin...
for(var i = 1; i <= 30; i++){ 
    var newWedge = new WedgePath(canvas);
    newWedge.label = "my_wedge_"+i;
    wedgeArray.push(newWedge);
} 

for(var i = 0; i < wedgeArray.length; i++){
    wedgeArray[i].logLabel()
}

But again, I get the last instance of WedgePath to be created.

This is driving me nuts. I apologise for the length of the question but I wanted to be as clear as possible.

END

==============================================================

Also, here's the code for dbInterface object should it be relevant.

function DatabaseInterface(db){

    var DB = db;

    this.sql = function(sql, arr, pSuccessHandler, pErrorHandler){

        successHandler = (pSuccessHandler) ? pSuccessHandler : this.defaultSuccessHandler;
        errorHandler = (pErrorHandler) ? pErrorHandler : this.defaultErrorHandler;

        DB.transaction(function(tx){

            if(!arr || arr.length == 0){
                tx.executeSql(sql, [], successHandler, errorHandler);
            }else{
                tx.executeSql(sql,arr, successHandler, errorHandler)
            }

        });

    }

    // ----------------------------------------------------------------
    // A Default Error Handler
    // ----------------------------------------------------------------

    this.defaultErrorHandler = function(transaction, error){
        // error.message is a human-readable string.
        // error.code is a numeric error code
        console.log('WebSQL Error: '+error.message+' (Code '+error.code+')');

        // Handle errors here
        var we_think_this_error_is_fatal = true;
        if (we_think_this_error_is_fatal) return true;
        return false;
    }


    // ----------------------------------------------------------------
    // A Default Success Handler
    // This doesn't do anything except log a success message
    // ----------------------------------------------------------------

    this.defaultSuccessHandler = function(transaction, results)
        {
            console.log("WebSQL Success. Default success handler. No action taken.");
        }

}

© Stack Overflow or respective owner

Related posts about JavaScript

Related posts about oop