IOS 10.3.1基于cordova的App在尝试写入IndexedDB

时间:2017-04-20 16:19:01

标签: ios cordova crash offline indexeddb

我正在开发一个基于cordova的多平台网络应用程序,使用sapui5 framework v1.44和indexedDB来存储数据。应用程序工作正常,直到最后的ios更新,10.3.1,现在它在尝试写入时崩溃到indexedDB。我正在使用put方法更新数据,我做了一个干净的应用程序安装。我尝试写入indexedDB的代码框是这样的:

    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版,但结果是一样的。其他人注意到了这一点或有任何想法如何解决这个问题? 谢谢 ķ

更新 我发现了这个问题:复杂的数据类型。由于IndexedDB支持保存和检索复杂的数据类型,我有一些属性,这些属性是我过去在一些ObjectStore中保存的数组或对象。这对我来说绝对是一个大问题,因为我能想到的唯一解决办法就是将复杂的字段固定下来,但由于我处理了大量数据,这会产生很大的性能问题。我希望ios开发团队能够尽快找到解决方案

2 个答案:

答案 0 :(得分:0)

您确定res []数组中的每个键都是有效键吗?这里有一个封闭的错误:

https://bugs.webkit.org/show_bug.cgi?id=170000

如果传入无效密钥,它将导致webkit崩溃。

此修复程序可能会包含在iOS的下一个公开发行版中。

要确定有效密钥是什么,请参阅W3.org规范的这一部分:

  

3.1.3键

     

为了有效地检索存储在索引数据库中的记录,每个记录都根据其密钥进行组织。如果值是以下ECMAScript [ECMA-262]类型之一,则称该值为有效密钥:Number原始值,String原始值,Date对象或Array对象。如果数组中的每个项都已定义并且是有效键(即稀疏数组不能是有效键)并且数组不直接或间接包含自身,则Array只是一个有效键。将忽略Array上的任何非数字属性,因此不会影响Array是否为有效键。如果值的类型为Number,则它只是一个有效密钥,如果它不是NaN。如果值是Date类型,则只有[[PrimitiveValue]]内部属性(由[ECMA-262]定义)不是NaN时,它才是有效密钥。符合要求的用户代理必须支持所有有效密钥作为密钥。

这是从这里取的:

https://www.w3.org/TR/IndexedDB/#key-construct

答案 1 :(得分:0)

不确定它是否是同一个问题,但我在iOS 10.3上遇到了崩溃,而我在任何其他浏览器中都没有。使用dexie包装器为indexedDB,我从表搜索中获取了所有记录:

db.table.toArray(function (results) {
    // process...
})

从Xcode到WebKit看起来像是一个线程问题,所以我刚刚添加了setTimeout( ... ,1),并为我解决了这个问题。