phonegap 代码中有问题的承诺,使用 webSQL (SQLite)
Problematic promises in phonegap code, using webSQL (SQLite)
我正在努力解决 Phonegap/Cordova 的错误。我正在连接的设备中构建和测试我的应用程序,这是我收到的错误:
INVALID_STATE_ERR: DOM 异常 11
None 我找到的解决方案有效。大部分都是针对使用ajax,这里不是这样的。我找到了另一个关于 phonegap 的,他们说这可能是因为设备还没有准备好,但我已经检查过我的设备已经准备好。
这是引发错误的代码(顺便说一句,我使用的是 Promise polyfill,因为它目前在 Cordova 中不受支持):
/**
* Clients insertion
* @param tx
* @param clientes
* @return {Promise}
*/
clientes = function(clientes) {
return new Promise(function(resolve, reject) {
var clientesCount = clientes.length;
if (clientesCont === 0){
resolve();
}
else {
APP.db.transaction(function(tx) {
$.each(clientes, function(i, cliente) {
var idclienteLocal;
// Current client
tx.executeSql("INSERT OR REPLACE INTO clientes (id, name, ...) " +
"VALUES " +
"(?,?,...)",
[cliente.id, cliente.name],
function(tx, res) {
clientesCount--;
idclienteLocal = res.insertId;
// Clien phones
telefonosCliente(tx, cliente, idclienteLocal).then(function() {
// Client credits
creditosCliente(tx, cliente, idclienteLocal).then(function() {
if (clientesCount === 0) {
resolve();
}
}).catch(function(error) {
reject('Error créditos cliente ' + cliente.empresa + ': ' + error);
});
}).catch(function(error) {
reject('Error teléfonos cliente ' + cliente.empresa + ': ' + error);
});
}, function(tx, error) {
reject(error.message);
});
});
});
}
});
}
我怀疑它可能与循环有关(我为此使用 jQuery),所以我尝试在前一个迭代完全解决后使用递归函数对每个迭代进行排队,但它甚至不能在浏览器中工作(第一个 procesarCliente() 调用中的 Promise,在 clientes() 中不会被解析)。这是修改后的代码:
/**
* Recursive function to process each client one after the other
* @param tx
* @param clientes
* @param cliente
* @return {Promise}
*/
procesarCliente = function(tx, clientes, cliente) {
return new Promise(function(resolve, reject) {
// Current client
tx.executeSql("INSERT OR REPLACE INTO clientes (id, name, ...) " +
"VALUES " +
"(?,?,...)",
[cliente.id, cliente.name,...],
function(tx, res) {
var idclienteLocal = res.insertId;
// Client phones
telefonosCliente(tx, cliente, idclienteLocal).then(function() {
// Client credits
creditosCliente(tx, cliente, idclienteLocal).then(function() {
if (clientes.length === 0) {
resolve();
}
else {
procesarCliente(tx, clientes, clientes.shift());
}
}).catch(function(error) {
reject('Error créditos cliente ' + cliente.empresa + ': ' + error);
});
}).catch(function(error) {
reject('Error teléfonos cliente ' + cliente.empresa + ': ' + error);
});
}, function(tx, error) {
reject(error.message);
});
});
},
/**
* Clients insertion
* @param tx
* @param clientes
* @return {Promise}
*/
clientes = function(clientes) {
return new Promise(function(resolve, reject) {
var cliente,
clientesCont = clientes.length;
if (clientesCont === 0){
resolve();
}
else {
APP.db.transaction(function(tx) {
cliente = clientes.shift();
procesarCliente(tx, clientes, cliente).then(function() {
resolve();
}).catch(function(error) {
reject(error);
});
});
}
});
}
关于修复第二种方法的任何帮助,最重要的是,如何让它在 phonegap 中工作?
编辑
我添加了一个验证码来检查本地数据库中的每个 table,令人惊讶的是,它显然只创建了两个 table,分别称为 "undefined" 和 "item"(我什至没有使用这样的table)。
验证码在这里:
if (APP.DEBUG) { // this is true
// Verify inserted data when triggered event 'app.load.all' just after the very last item in the DB has been inserted
$wrapper.on('app.load.all', function() {
APP.db.transaction(function(tx) {
console.log('Verifying DB');
tx.executeSql("SELECT name FROM sqlite_master WHERE type='table'", [],
function(tx, res) {
if (res.rows.length) {
$.each(res.rows, function(i, tabla) {
if (tabla.name !== '__WebKitDatabaseInfoTable__') {
console.log('Verifying table ' + tabla.name);
tx.executeSql("SELECT * FROM " + tabla.name, [],
function(tx, res) {
console.log("Table " + tabla.name + " has " + res.rows.length + " records");
},
function(tx, error) {
console.log('Error verifying table ' + tabla.name + ':' + error.message);
});
}
});
}
}, function(tx, error) {
console.log('Error verifying DB tables: ' + error.message);
});
});
});
}
这导致这些行被 "Web Console" 过滤:
I/Web Console(14391): Verifying DB:1085
I/Web Console(14391): Verifying table undefined:1091
I/Web Console(14391): Verifying table item:1091
I/Web Console(14391): Error Verifying table undefined:no such table: undefined:1100
I/Web Console(14391): Error Verifying table item:no such table: item:1100
这对我来说完全陌生
我终于找到问题了:
我可以将浏览器中的 SQLResult 对象视为数组,但这显然在 phonegap 构建中不起作用(可能是因为 Android WebView 浏览器)。因此,实际上并没有插入任何记录。
我不得不摆脱 jQuery 循环(他们不会获取 Phonegap 应用程序中的每个项目),而是使用 for 循环,并最终使用 [= SQLResult 对象的 22=]item() 方法:
差:
$.each(res.rows, function(i, item) {
//...
}
好:
var item;
for (var i = 0; i < res.rows.length; i++) {
item = res.rows.item(i);
}
我正在努力解决 Phonegap/Cordova 的错误。我正在连接的设备中构建和测试我的应用程序,这是我收到的错误:
INVALID_STATE_ERR: DOM 异常 11
None 我找到的解决方案有效。大部分都是针对使用ajax,这里不是这样的。我找到了另一个关于 phonegap 的,他们说这可能是因为设备还没有准备好,但我已经检查过我的设备已经准备好。
这是引发错误的代码(顺便说一句,我使用的是 Promise polyfill,因为它目前在 Cordova 中不受支持):
/**
* Clients insertion
* @param tx
* @param clientes
* @return {Promise}
*/
clientes = function(clientes) {
return new Promise(function(resolve, reject) {
var clientesCount = clientes.length;
if (clientesCont === 0){
resolve();
}
else {
APP.db.transaction(function(tx) {
$.each(clientes, function(i, cliente) {
var idclienteLocal;
// Current client
tx.executeSql("INSERT OR REPLACE INTO clientes (id, name, ...) " +
"VALUES " +
"(?,?,...)",
[cliente.id, cliente.name],
function(tx, res) {
clientesCount--;
idclienteLocal = res.insertId;
// Clien phones
telefonosCliente(tx, cliente, idclienteLocal).then(function() {
// Client credits
creditosCliente(tx, cliente, idclienteLocal).then(function() {
if (clientesCount === 0) {
resolve();
}
}).catch(function(error) {
reject('Error créditos cliente ' + cliente.empresa + ': ' + error);
});
}).catch(function(error) {
reject('Error teléfonos cliente ' + cliente.empresa + ': ' + error);
});
}, function(tx, error) {
reject(error.message);
});
});
});
}
});
}
我怀疑它可能与循环有关(我为此使用 jQuery),所以我尝试在前一个迭代完全解决后使用递归函数对每个迭代进行排队,但它甚至不能在浏览器中工作(第一个 procesarCliente() 调用中的 Promise,在 clientes() 中不会被解析)。这是修改后的代码:
/**
* Recursive function to process each client one after the other
* @param tx
* @param clientes
* @param cliente
* @return {Promise}
*/
procesarCliente = function(tx, clientes, cliente) {
return new Promise(function(resolve, reject) {
// Current client
tx.executeSql("INSERT OR REPLACE INTO clientes (id, name, ...) " +
"VALUES " +
"(?,?,...)",
[cliente.id, cliente.name,...],
function(tx, res) {
var idclienteLocal = res.insertId;
// Client phones
telefonosCliente(tx, cliente, idclienteLocal).then(function() {
// Client credits
creditosCliente(tx, cliente, idclienteLocal).then(function() {
if (clientes.length === 0) {
resolve();
}
else {
procesarCliente(tx, clientes, clientes.shift());
}
}).catch(function(error) {
reject('Error créditos cliente ' + cliente.empresa + ': ' + error);
});
}).catch(function(error) {
reject('Error teléfonos cliente ' + cliente.empresa + ': ' + error);
});
}, function(tx, error) {
reject(error.message);
});
});
},
/**
* Clients insertion
* @param tx
* @param clientes
* @return {Promise}
*/
clientes = function(clientes) {
return new Promise(function(resolve, reject) {
var cliente,
clientesCont = clientes.length;
if (clientesCont === 0){
resolve();
}
else {
APP.db.transaction(function(tx) {
cliente = clientes.shift();
procesarCliente(tx, clientes, cliente).then(function() {
resolve();
}).catch(function(error) {
reject(error);
});
});
}
});
}
关于修复第二种方法的任何帮助,最重要的是,如何让它在 phonegap 中工作?
编辑
我添加了一个验证码来检查本地数据库中的每个 table,令人惊讶的是,它显然只创建了两个 table,分别称为 "undefined" 和 "item"(我什至没有使用这样的table)。
验证码在这里:
if (APP.DEBUG) { // this is true
// Verify inserted data when triggered event 'app.load.all' just after the very last item in the DB has been inserted
$wrapper.on('app.load.all', function() {
APP.db.transaction(function(tx) {
console.log('Verifying DB');
tx.executeSql("SELECT name FROM sqlite_master WHERE type='table'", [],
function(tx, res) {
if (res.rows.length) {
$.each(res.rows, function(i, tabla) {
if (tabla.name !== '__WebKitDatabaseInfoTable__') {
console.log('Verifying table ' + tabla.name);
tx.executeSql("SELECT * FROM " + tabla.name, [],
function(tx, res) {
console.log("Table " + tabla.name + " has " + res.rows.length + " records");
},
function(tx, error) {
console.log('Error verifying table ' + tabla.name + ':' + error.message);
});
}
});
}
}, function(tx, error) {
console.log('Error verifying DB tables: ' + error.message);
});
});
});
}
这导致这些行被 "Web Console" 过滤:
I/Web Console(14391): Verifying DB:1085
I/Web Console(14391): Verifying table undefined:1091
I/Web Console(14391): Verifying table item:1091
I/Web Console(14391): Error Verifying table undefined:no such table: undefined:1100
I/Web Console(14391): Error Verifying table item:no such table: item:1100
这对我来说完全陌生
我终于找到问题了:
我可以将浏览器中的 SQLResult 对象视为数组,但这显然在 phonegap 构建中不起作用(可能是因为 Android WebView 浏览器)。因此,实际上并没有插入任何记录。
我不得不摆脱 jQuery 循环(他们不会获取 Phonegap 应用程序中的每个项目),而是使用 for 循环,并最终使用 [= SQLResult 对象的 22=]item() 方法:
差:
$.each(res.rows, function(i, item) {
//...
}
好:
var item;
for (var i = 0; i < res.rows.length; i++) {
item = res.rows.item(i);
}