Javascript 在IOS中触发触摸时,HTML5 Web SQL事务被跳过,没有错误

Javascript 在IOS中触发触摸时,HTML5 Web SQL事务被跳过,没有错误,javascript,iphone,sql,ios,html,Javascript,Iphone,Sql,Ios,Html,我在IOS设备上进行数据库事务时遇到问题。 如果用户不触摸手机,一切正常。 如果用户点击/滚动/触摸屏幕,一些事务会直接调用其successCallback,而不会调用实际的事务回调 此处的简化示例: 要进行测试,只需在IOS上的mobile safari中打开,加载时不要触摸设备。您将看到生成的调试消息列表,如下所示: database is running table will be cleared store method called for '10'. about to insert

我在IOS设备上进行数据库事务时遇到问题。 如果用户不触摸手机,一切正常。 如果用户点击/滚动/触摸屏幕,一些事务会直接调用其successCallback,而不会调用实际的事务回调

此处的简化示例:

要进行测试,只需在IOS上的mobile safari中打开,加载时不要触摸设备。您将看到生成的调试消息列表,如下所示:

database is running
table will be cleared
store method called for '10'.
about to insert '10'.
transaction successful for '10'
store method called for '9'.
about to insert '9'.
transaction successful for '9'
store method called for '8'.
about to insert '8'.
transaction successful for '8'
[...]
现在,重新加载页面,在加载的同时,滚动并随机点击。 您将看到一些将要插入的。。。消息丢失

database is running
table will be cleared
store method called for '10'.
about to insert '10'.
transaction successful for '10'
store method called for '9'.
about to insert '9'.
transaction successful for '9'
store method called for '8'.
transaction successful for '8' <-- WHERE IS MY "about to insert '8'." ???
store method called for '7'.
about to insert '7'.
transaction successful for '7'
[...]
这是因为transactionCallback被完全跳过!但是为什么呢?为什么会触发successCallback而不是errorCallback

[这是一个简化的示例,请不要告诉我不要执行此setTimeout操作。在现实世界中,数据是异步加载然后插入的…:]

我认为这里也存在类似的问题,但也没有解决方案或提示


有什么想法吗?我被卡住了。。。谢谢

Web Workers和OpenDatabaseSync解决了我网站上的相同问题。除了iOS4.x和Android上不支持web workers之外,我们可以在iOS5上为这些web workers和web workers实现旧方法

下面这个非常基本的例子使用一个循环,在每次插入后,对屏幕进行500次写入操作。最后进行查询以返回表中的行数。现在我们可以看到,即使有很多滚动,事务也不会被跳过

本例旨在测试iPhone或iPad插入时滚动的弹性

需要两个页面,一个html页面和工作人员的单独javascript文件。html页面也是如此

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport"/>
    <meta name="apple-mobile-web-app-capable" content="yes" />
    <meta name="apple-mobile-web-app-status-bar-style" content="black" />
    <title></title>
    <script src="../scripts/jquery-1.6.2.min.js" type="text/javascript"></script>
    <style type="text/css">
    body
    {
    background-color:Black;
    }
    .number
    {
    color:#00FF00;
    font-family:Courier New;
    font-size:12pt;
    }
    button
    {
    position:fixed;
    right:5px;
    top:5px;
    padding:15px;
    }
    </style>
    <script type="text/javascript">
    var worker;
    $(document).ready(function () {

        worker = new Worker('worker1.js');
        worker.addEventListener('message', function (e) {
        $("#test").html(new Date().toLocaleTimeString() + " " + e.data.message + "<BR/>" + $("#test").html());
        if (e.data.complete == true) {
            worker.terminate();
        }
        }, false);
    });

    function stop() {
        worker.terminate();
    }
    </script>

</head>
<body>
    <form id="form1" onsubmit="return false">
    <div id="test" class="number">
    <button onclick="stop()">Stop</button>
    </div>
    </form>
</body>
</html>
和worker1.js

var wdb = {};
wdb.db = openDatabaseSync('test', '1.0', 'DB test', 1024);

doQuery("CREATE TABLE IF NOT EXISTS test(abc INTEGER PRIMARY KEY);");
doQuery("DELETE FROM test"); // optional

for (var i = 0; i < 500; i++) {
    doQuery("INSERT INTO test(abc) VALUES( " + i + " );");
    postMessage({ message: "Inserted " + i.toString(), complete: false });
}

var summary= doQuery("SELECT COUNT(*) AS Total FROM test;");
postMessage({ message: "Found " + summary.item(0).Total.toString() + " rows", complete: true });

function doQuery(sql) {
    wdb.db.transaction(function (tx) {
    rs = tx.executeSql(sql, []);
    });
    return rs.rows;
}

我们的测试表明,这种行为在键盘显示时也会发生,并且会阻止onblur或onfocus事件中的事务,尽管不是onkey{down | up | press}。使用setTimeout将导致严重的性能问题。我们发现,即使没有调用事务回调,也会触发.transaction success回调,因此我们提出了一种适合我们的方法:

var oldOpenDatabase = window.openDatabase;
window.openDatabase = function() {
    var db = oldOpenDatabase.apply(window, arguments);

    var oldTrans = db.transaction;
    db.transaction = function(callback, err, suc) {
        var db = this;
        var params = arguments;
        var hasRun = false;
        oldTrans.call(db, function(tx){
            hasRun = true; callback(tx);
        }, err||function(){}, function(tx) {
            if(hasRun){
                if (suc != undefined)
                    suc(tx); 
                return;
            }
            else {
                oldTrans.apply(db, params);
            }
        });
    }

    return db;
}

此代码检查事务回调是否已在成功处理程序中触发,如果未触发,则为其提供另一次机会。

Addon:在iOS 4.3中工作,在iOS 5i中失败。我也有同样的问题,让我们期待iOS 5.1的帮助我仍在寻找解决方案:等待iOS 5.1不是一个选项,因为页面必须使用iOS>=4…增加事务之间的超时时间可以减少问题,虽然不完全是这样,但我注意到-但你不能依赖它:但是现在w3取消了他们在这个html数据库解决方案上的工作,我认为这永远不会得到解决。当您传递无效错误或suc回调时的错误处理并不总是与本机API完全相同,但对我们来说,克服iOS WebSQL中的这一严重故障所付出的代价很小。非常酷的解决方案,我们现在已经实现了,并且惊讶地发现更多的人没有发现这个iOS错误是一个主要问题,或者他们没有注意到他们的数据丢失。干得好@EionRobb.令人印象深刻!我想使用您的解决方案,只有一个问题:它只重新启动事务一次,还是递归地重新启动事务,直到成功?我的意思是,如果第二次尝试与第一次尝试一样失败怎么办?@schory不,如果第二次尝试失败,您的错误函数回调将被通知。这似乎并不是一个神奇的解决办法,至少对我来说不是。我正在使用这个修补程序库,并在iOS 7上进行测试。我也为readTransaction函数复制了上面的代码,但还没有修复它。可以找到我正在使用的修改代码。任何时候都不会调用回调、err或suc处理程序,也不会将任何内容记录到控制台。我们还使用WebWorkers解决了这个iOS错误。但我们现在怀疑,至少对于焦点/模糊事件中断,相对于触摸/滚动事件中断,它并没有完全解决问题-只是显著减少了它。。。