【问题标题】:IOS 10.3.1 cordova based App crashes when trying to write to IndexedDB尝试写入 IndexedDB 时,基于 IOS 10.3.1 cordova 的应用程序崩溃
【发布时间】:2017-09-17 09:39:54
【问题描述】:

我正在使用 sapui5 框架 v1.44 和 indexedDB 开发一个基于科尔多瓦的多平台网络应用程序来存储数据。该应用程序运行良好,直到最后一次 ios 更新 10.3.1,现在它在尝试编写时崩溃到索引数据库。我正在使用 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.我省略了部分代码。 这在以前版本的 ios 上运行良好,我想我已经安装了 10.2.1,现在它在调用 put 方法后就崩溃了。我现在尝试将 ios 升级到 10.3.2 的测试版,但结果是一样的。其他人注意到这一点或对如何解决此问题有任何想法吗? 谢谢 克

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

【问题讨论】:

  • 控制台有错误吗?
  • 不,一个也没有

标签: ios cordova crash offline indexeddb


【解决方案1】:

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

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

它看起来如果你传入一个无效的密钥,它会导致 webkit 崩溃。

此修复可能会包含在 iOS 的下一个公开版本中。

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

3.1.3 键

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

这是从这里拍摄的:

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

【讨论】:

  • 感谢您的回复。在您提到的错误报告之前我已经看到了,但我认为这不是我的情况。确实,我的某些 objectStores 有复合键,但是如果为 null 或未定义,我会预先格式化传递给空字符串的每个值,这并不能解释为什么,如果错误与复合键有关,即使使用简单的也会发生这种情况其他 ObjectStore 的键以及为什么这一切在我以前的 ios 版本的 ios 10.2.1 中运行良好。我正在考虑更多关于这个新版本的 ios 引入的一些安全检查,它会阻止一切......
【解决方案2】:

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

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

并从 Xcode 引发了 WebKit 中看起来像是线程问题的问题,所以我只添加了 setTimeout( ... ,1) 并解决了我的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-14
    • 1970-01-01
    • 2019-05-04
    • 1970-01-01
    • 1970-01-01
    • 2018-02-12
    • 1970-01-01
    相关资源
    最近更新 更多