我正在开发一个基于Cordova的多平台Web应用程序,使用SAPUI5 Framework v1.44和indexedDB用于存储数据。该应用程序正常运行良好,上一次iOS更新,10.3.1,现在试图写入indexedDB时它崩溃了。我正在使用POT方法来更新数据,然后进行了整个应用程序的安装。我尝试写入索引的代码框架是:
writeToIDB: function (objStoreName, result, success, error) {
//Asynchronous function
var defer = Q.defer();
var res = [];
if (!!result && Array.isArray(result)) {
res = result;
} else if (!!result && result.hasOwnProperty("results") && Array.isArray(result.results)) {
res = result.results;
} else if (!!result && typeof result === 'object') {
res.push(result);
}
if (res.length >= 0) {
if (window.myDB) {
if (!window.myDB.objectStoreNames.contains(objStoreName)) {
console.log("ObjectStore for " + objStoreName + " doesn't exist");
if (error) {
error("ko")
} else {
defer.reject("ko");
}
} else {
var oTransaction = window.myDB.transaction([objStoreName], "readwrite");
var oDataStore = oTransaction.objectStore(objStoreName);
oTransaction.oncomplete = function (event) {
console.log("Transaction completed: database modification for " + objStoreName + " finished.");
if (success) {
success();
} else {
defer.resolve("ok");
}
};
oTransaction.onerror = function (event) {
console.log("Transaction for " + objStoreName + " not opened due to error. Check for duplicate items or missing properties!");
console.log(event.target.error);
if (error) {
error("ko")
} else {
defer.reject("ko");
}
};
var oRecord = {};
for (var i = 0; i < res.length; i++) {
oRecord = res[i];
oDataStore.put(oRecord);
}
}
} else {
this.createIDB().then(
function (resCreate) {
console.log("DB Created successfully");
if (!window.myDB.objectStoreNames.contains(objStoreName)) {
console.log("ObjectStore for " + objStoreName + " doesn't exist");
if (error) {
error("ko")
} else {
defer.reject("ko");
}
} else {
var oTransaction = window.myDB.transaction([objStoreName], "readwrite");
var oDataStore = oTransaction.objectStore(objStoreName);
oTransaction.oncomplete = function (event) {
console.log("Transaction completed: database modification for " + objStoreName + " finished.");
if (success) {
success();
} else {
defer.resolve("ok");
}
};
oTransaction.onerror = function (event) {
console.log("Transaction for " + objStoreName + " not opened due to error. Check for duplicate items or missing properties!");
console.log(event.target.error);
if (error) {
error("ko")
} else {
defer.reject("ko");
}
};
var oRecord = {};
for (var i = 0; i < res.length; i++) {
oRecord = res[i];
oDataStore.put(oRecord);
}
}
}.bind(this),
function (err) {
console.log("DB Creation failed");
if (error) {
error("ko")
} else {
defer.reject("ko");
}
}.bind(this)
);
}
} else {
if (error) {
error("ko")
} else {
defer.reject("ko");
}
}
if (typeof success === 'undefined' && typeof error === 'undefined') {
return defer.promise;
}
},
p.s.i省略了代码的一部分。这与以前版本的iOS合作正常,我认为我已经安装了10.2.1,现在调用PUT方法后仅崩溃。我现在尝试将iOS升级到10.3.2的Beta,但结果是相同的。其他人注意到这一点,或者对如何解决这个问题有任何想法?谢谢k
更新我发现了问题:复杂的数据类型。由于IndexedDB支持保存和检索复杂的数据类型,因此我有一些属性是用于保存在某些对象店中的数组或对象。这对我来说绝对是一个大问题,因为我能想到的唯一解决方法是刺激复杂的领域,但是由于我使用大量数据,这会造成一个很大的性能问题。我希望iOS开发人员团队能尽快找到解决方案
您确定res []数组中的每个密钥是有效的键吗?这里有一个封闭的错误:
https://bugs.webkit.org/show_bug.cgi?id=170000
看起来,如果您通过无效的键,它将导致Webkit崩溃。
此修复程序可能包含在iOS的下一个公开版本中。
确定什么有效键是W3.org规格的这一部分:
3.1.3键
为了有效检索存储在索引数据库中的记录,每个记录都是根据其密钥组织的。如果值是以下ecmascript [ECMA-262]类型之一:数字原始值,字符串原始值,日期对象或数组对象之一,则据说是有效的密钥。当定义数组中的每个项目并且是有效的密钥(即稀疏数组不能是有效的键(,并且数组不直接或间接包含自身,数组只是一个有效的密钥。数组上的任何非数字属性都被忽略,因此不会影响数组是否是有效的键。如果该值是类型编号,则仅在不是NAN时才是有效的密钥。如果值是类型日期的值,则仅当[ECMA-262]定义的内部属性[[PrimitiveValue]]内部属性不是NAN时,它仅是有效的密钥。符合用户代理必须支持所有有效键作为密钥。
这是从这里获取的:
https://www.w3.org/tr/indexeddb/#key-construct
不确定这是否是同一问题,但是我在iOS 10.3上遇到了崩溃,我没有在任何其他浏览器中获得。使用dexie包装器作为indexeddb,我从表搜索中获取了所有记录:
db.table.toArray(function (results) {
// process...
})
并从Xcode那里得到了WebKit中看起来像是线程问题的火焰,所以我刚刚添加了setTimeout( ... ,1)
,并为我围绕问题而入侵。