2012-03-26 19 views
2

我创建了一个函数,它将从我的数据库中返回字符串“path”。SQLite查询中的javascript for-loop

function getAudio(mid, cb) { 
    //mid is an array containing the id to some multimedia files. 
    for(i=0; i < mid.length; i++) { 

     db.transaction(function(tx) { 
       tx.executeSql('SELECT * FROM Multimedia WHERE Mid=' + mid[i] + ' AND Type=' + 2, [], function(tx, results) {  
       //type=2 is audio. (type=1 is picture file etc) There is only one audiofile in the array. 
        if(results.rows.length > 0) { 
         path = results.rows.item(0).Path; 
         cb(path); 
        } 
       }, errorCB); 
     }, errorCBQuery); 

    }//end for 
}//end getAudio() 

当我删除了for循环,查询是全成,当for循环是存在的, errorCBQuery或errorCB被调用。

任何想法如何解决这个问题?谢谢:)

+0

大声笑,这只是一个错字:p 已经有很多删除和添加代码的最后一个小时。 我的坏:) – TorK 2012-03-26 11:40:44

+0

@ T.J.Crowder好的,谢谢你通知我。 *编辑* :) – TorK 2012-03-26 11:57:15

+0

你应该使用参数化的sql而不是使用字符串连接,以保护自己免受SQL注入。鉴于你通过的数组参数,我想它会看起来像'tx.executeSql('SELECT * FROM Multimedia WHERE Mid =?AND Type =?',[mid [i],2]' – hugomg 2012-03-26 13:09:41

回答

6

这是经典的关闭问题。 transaction是一个异步调用,这意味着您的循环在您传入的函数被触发之前完成。该函数有一个变量的持久引用i变量,而不是您调用transaction时的副本。因此,每个函数(您在每个循环中生成一个函数)都会看到i == mid.length,因此mid[i]undefined,并且SQL会变得混乱。

你需要做的是将回调函数关闭在另一个变量上,这个变量在循环过程中不会改变。通常的方式做到这一点是使用工厂函数:

function getAudio(mid, cb) { 
    //mid is an array containing the id to some multimedia files. 
    for(i=0; i < mid.length; i++) { 

     db.transaction(makeTx(mid[i]), errorCBQuery); 

    }//end for 

    function makeTx(val) { 
     return function(tx) { 
      tx.executeSql('SELECT * FROM Multimedia WHERE Mid=' + val + ' AND Type=' + 2, [], function(tx, results) {  
      //type=2 is audio. (type=1 is picture file etc) There is only one audiofile in the array. 
       if(results.rows.length > 0) { 
        path = results.rows.item(0).Path; 
        cb(path); 
       } 
      }, errorCB); 
     }; 
    } 

}//end getAudio() 

还有,我传球mid[i]makeTx功能,回报将获得通过成为transaction功能。我们返回的函数在调用makeTxval参数时关闭,该参数创建它,但不会更改。

这是一个最小重写的代码;你或许可以更进一步。例如,请参阅关于re参数化语句的问题的评论。


旁注:它看起来并不像你声明ipath任何地方。如果确实如此,那么你就会沦为The Horror of Implicit Globals。推荐宣布他们。

+0

Thanx,完美的作品:) – TorK 2012-03-26 12:30:28

+1

如果解决方案适用于+1。 – 2012-03-26 12:49:31

+0

@YaqubAhmad:在我获得15点声望之前,无法赞成。但我在“有用的帖子”回答“是”:) – TorK 2012-03-26 13:47:27