由函数追加的全局数组在其他地方显示为零长度

时间:2011-01-27 15:55:04

标签: javascript arrays

我已将数组标签声明在我的脚本顶部

var labels = [];

调用一个函数retrieveLabels来附加到这个数组:

     function retrieveLabels() {
      labels = [];
      var getLabelsQuery = "SELECT DISTINCT label FROM items ORDER BY label;"
      db.transaction(function(tx) {
           tx.executeSql(getLabelsQuery, [],
                function(tx, labelsResults) {
                     for (var x = 0; x < labelsResults.rows.length; x++) {
                          var labelsRow = labelsResults.rows.item(x);
                          labels.push(labelsRow['label']);
                     }
                     console.log(labels.length);
                     console.log(labels);
                }
           );
      });
 }

第一个控制台消息显示34个项目。 第二个控制台消息显示[“label1”,“label2”.....“label34”]

我在这里调用函数的地方是:

else {
 init_db();
 retrieveLabels();
 console.log(labels.length);
 console.log(labels);

}

第一个控制台消息显示0个项目。 第二个控制台消息显示[“label1”,“label2”.....“label34”]

为什么这会突然变成0长度数组?或者在retrieveLabels内部进行了修改?

2 个答案:

答案 0 :(得分:1)

我会说tx.executeSql()是异步的,而作为argument3传递的匿名函数实际上是在 retrieveLabels();返回后执行的。

因此,当您调用第二个console.log(labels.length);时,查询可能尚未执行。

这是一个稍微修改过的函数版本,它将回调作为参数,并在填充labels数组后调用它:

function retrieveLabels(callback) {
    var labels = [];
    var getLabelsQuery = "SELECT DISTINCT label FROM items ORDER BY label;"
    db.transaction(function(tx) {
        tx.executeSql(getLabelsQuery, [],
            function(tx, labelsResults) {
                for (var x = 0; x < labelsResults.rows.length; x++) {
                    var labelsRow = labelsResults.rows.item(x);
                    labels.push(labelsRow['label']);
                }               

                callback(labels);
            }           
        );      
    }); 
}

然后你可以这样调用这个函数:

init_db();
retrieveLabels(function(label) {
    console.log(labels.length);
    console.log(labels);
});

答案 1 :(得分:0)

您的调用db.transaction或tx.executeSql可能是异步的。这意味着当你调用console.log(labels.length)时,数组标签还没有被填充;的console.log(标签);在else语句中。

您可以通过编辑代码进行检查:

db.transaction(function(tx) {
       tx.executeSql(getLabelsQuery, [],
            function(tx, labelsResults) {
                 for (var x = 0; x < labelsResults.rows.length; x++) {
                      var labelsRow = labelsResults.rows.item(x);
                      labels.push(labelsRow['label']);
                 }
                 console.log("tx.exectureSQL done");
            }
       );
  });

else {
    init_db();
    retrieveLabels();
    console.log("else done");
}
通过这种方式,你可以看到实际发生的事情。