我有一个Web应用程序的初始化过程,该过程以递归方式执行WebSQL查询。
它涉及一个名为actions
的数组,并将几个函数推入该数组。每个函数都返回一个Promise,当执行WebSQL查询时,Promise将被解析。这些功能大多数涉及检查表是否具有应包含的所有列,如果没有,则删除表并使用正确的列配置重新创建。 (用户数据存储在服务器端,因此下一次登录将重新填充表。)
数组中的每个函数必须先完成执行,然后才能启动下一个函数。 actions
数组中每个函数的基本骨架是:
actions.push(function() {
var d = $q.defer();
Database.recreateTable(table).then(function() {
d.resolve("Success");
}, function(e) { d.resolve(e);});
return d.promise
})
(即使数据库功能失败,该行也要解决,以确保仍对后续表进行检查。)
Database.recreateTable
是Angular服务中的一个函数:
var recreateTable = function(table) {
var def = $q.defer();
execute("DROP TABLE IF EXISTS " + table).then(function() {
createTable(table).then(function() {
def.resolve();
}, function(error) {
ValidatorService.log(getScriptName(), error);
def.reject(error);
});
}, function (error) {
ValidatorService.log(getScriptName(), error);
def.reject(error);
});
return def.promise;
}
其中createTable
仅是以下内容:
var createTable = function(table) {
var def = $q.defer();
var q = "CREATE TABLE IF NOT EXISTS " + table + " (" + getColumns(table, true, true) + ")";
execute(q).then(function(s) {
def.resolve();
}, function (error) {
def.reject(error);
});
return def.promise;
}
和execute
是WebSQL事务的包装,涵盖了Web使用和Cordova使用:
var execute = function (query, bindings) {
bindings = typeof bindings !== 'undefined' && typeof bindings !== 'null' ? bindings : [];
var deferred = $q.defer();
if (db === undefined || db === null) { //initialize first if hasn't been done yet
init().then(executeQuery(), function(error) {} );
}
else {
executeQuery();
}
function executeQuery() {
if (window.cordova) {
$cordovaSQLite.execute(db, query, bindings).then(function (result) {
deferred.resolve(result);
}, function (fail) {
ValidatorService.log(getScriptName(), JSON.stringify(fail));
deferred.reject(fail);
});
}
else {
db = window.openDatabase("database.db", '1.0', 'auto', 1024 * 1024 * 100);
db.transaction(function(tx) {
tx.executeSql(query, bindings, function (tx, result) {
deferred.resolve(result);
}, function (tx, fail) {
deferred.resolve(fail);
});
});
}
}
return deferred.promise;
}
actions
数组中的所有函数都使用以下代码一个接一个地执行:
function executeRun() {
var d = $q.defer();
function multi(i) {
if (actions.length > 0 && i < actions.length) {
actions[i]().then(function(s) {
multi(i+1);
}, function(e) {
multi(i+1);
})
}
else {
d.resolve();
}
}
multi(0);
return d.promise;
}
此刻,编写该指令以继续执行该操作是否成功,以便无论如何都将检查后续表。这些动作是一个接一个地执行的,而不是异步执行的,因为某些动作可能会或可能不会添加,具体取决于actions
数组中的早期条目。
这背后的想法似乎很简单,但是问题是循环中进行了几次迭代,查询只是挂起而不返回响应,因此永远不会触发成功和错误回调。似乎没有任何押韵或原因在这种情况下发生,并且似乎仅在iOS Cordova上发生,当依赖于这些表的其他进程返回“无此表”错误时。 Android Cordova没有遇到此问题。
我以前曾在台式机Chrome浏览器中看到过这种情况,即使使用“清除站点数据”按钮也无法停止。唯一可以解决的问题是重新安装Chrome。