JavaScript变量范围/ OOP和回调函数需要帮助

时间:2010-05-18 09:45:13

标签: javascript jquery oop scope

我认为这个问题超出了典型的变量范围和封闭内容,或者我可能是个白痴。不管怎么说......

我正在jQuery插件中动态创建一堆对象。该对象看起来像这样

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

jQuery插件看起来像这样

(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);

所以...插件创建了一堆wedgeObjects,然后为每一个调用'globalFunction',传入最新的WedgePath实例。全局函数看起来像这样。

function globalFunction(indicator_id, pWedge){

    var targetWedge = pWedge; 
    targetWedge.logLabel();

}

接下来会发生的事情是控制台正确记录每个楔形标签。但是,我需要在globalFunction中复杂一点。所以它实际上看起来像这样......

function globalFunction(indicator_id, pWedge){

        var targetWedge = pWedge; 

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

            targetWedge.logLabel();

        })

    }

这里有很多事情,所以我会解释一下。我正在使用客户端数据库存储(WebSQL我称之为)。 'dbInterface'是我创建的一个简单javascript对象的实例,它处理与客户端数据库交互的基础知识[显示在本问题的末尾]。 executeSql方法最多需要4个参数

  • SQL字符串
  • 可选参数数组
  • 可选的onSuccess处理程序
  • 一个可选的onError处理程序(本例中未使用)

我需要做的是:当WebSQL查询完成时,它会获取一些数据并操纵特定楔形的某些属性。但是,当我在onSuccess处理程序中的WedgePath实例上调用'logLabel'时,我得到了在插件代码中创建的最后一个WedgePath实例的标签。

现在我怀疑问题出在var newWedge = new WedgePath(canvas);线。所以我尝试将每个newWedge推入一个数组,我认为这会阻止该行在每次迭代时替换或覆盖WedgePath实例......

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()
}

但是,我再次创建了WedgePath的最后一个实例。

这让我疯了。我为问题的长度道歉,但我希望尽可能清楚。

END

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

此外,这里是dbInterface对象的代码,如果它是相关的。

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.");
  }    
}

2 个答案:

答案 0 :(得分:3)

我猜这是因为客户端数据库存储在AJAX调用时会异步运行。这意味着它不会停止调用链以等待调用方法的结果。

因此,javascript引擎在运行globalFunction之前完成for循环。

要解决此问题,您可以在闭包内执行db查询。

function getDataForIndicatorAndRegion(indicator_id, region_id, pWedge){ 
    return function (targetWedge) { 
        someSql = "SELECT dataRows.status FROM dataRows WHERE indicator_id = ? AND region_id = ?"; 
        dbInterface.sql(someSql, [indicator_id, region_id], function(transaction, result) {
            targetWedge.changeColor(randomHex());
        });
    }(pWedge);
}

这样就可以为每次执行保留pWedge。因为第二种方法是自己调用它并发送pWedge现在作为参数。

编辑:更新了评论中的代码。并改变了它。回调函数可能不应该是自调用的。如果它自己调用它,函数的结果将作为参数传递。此外,如果它不起作用,请尝试传递其他参数。

答案 1 :(得分:0)

我怀疑你的问题是全局函数内的修改后的闭包:

function(transaction, result){

        targetWedge.logLabel();

    })

阅读this