我创建了一个函数,它将从我的数据库返回字符串“path”。
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 被调用。
有想法该怎么解决这个吗?谢谢 :)
这是经典的闭包问题。transaction http://www.w3.org/TR/webdatabase/#dom-database-transaction is an 异步call,这意味着循环在您传入的函数被触发之前完成。该函数有一个持久的参考 to the i
变量,而不是您调用时的副本transaction
。所以每个函数(你在每个循环上生成一个)都看到i == mid.length
因此mid[i]
is 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
函数,其中returns将被传递到的函数transaction
。我们返回的函数关闭val
调用的参数makeTx
它创造了它,它不会改变。
那是一个minimal重写代码;你也许可以更进一步。例如,请参阅missingno对参数化语句问题的评论。
旁注:看起来你并没有声明i
or path
任何地方。如果这是真的,那么你就陷入了困境隐式全局变量的可怕之处 http://blog.niftysnippets.org/2008/03/horror-of-implicit-globals.html。建议声明它们。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)