如Safari 客户端存储和离线应用程序编程指南,回滚 HTML 5 Web SQL 数据库事务是通过在作为 的错误回调提供的回调函数中返回 true 来完成的事务 executeSql
方法:
每个查询的错误处理回调
相当简单。如果
回调返回true,整个
事务被回滚。如果
回调返回 false,则
交易继续进行,就像什么都没有发生一样
出了问题。因此,如果您是
执行可选的查询 — if
该特定查询失败
不应导致交易
失败——你应该传入一个回调
返回 false。如果失败
查询应该导致整个
交易失败,你应该通过
在返回 true 的回调中。
例如,如果我有以下事务(假设“users”表对“用户名”字段有一个唯一约束,并且用户名“test”已经存在 - 我试图再次插入,这应该会导致约束错误) :
database.transaction(function(transaction) {
transaction.executeSql(
"INSERT INTO users (username) VALUES('test')",
null,
dataCallback,
errorCallback
);
});
function errorCallback() {
return true; //this causes the rollback
}
我有两个问题:
-
如果我必须在事务中包含许多操作(例如我必须使用ajax向服务器发送一些数据并等待响应等)并且用户在执行之前重新加载页面响应已到达(这意味着 errorCallback 不会被调用),事务会被提交还是会失败?
-
有人知道如何手动回滚 Web SQL 事务吗?例如,如果我想根据 ajax 调用的结果回滚事务,该怎么做?我是否应该运行包含错误的查询以确保调用错误回调?
谢谢。
As written in the Safari Client-Side Storage and Offline Applications Programming Guide, rolling back a HTML 5 Web SQL Database transaction is done by returning true in the callback function provided as an error callback to a transaction the executeSql
method:
The per-query error-handling callback
is rather straightforward. If the
callback returns true, the entire
transaction is rolled back. If the
callback returns false, the
transaction continues as if nothing
had gone wrong. Thus, if you are
executing a query that is optional—if
a failure of that particular query
should not cause the transaction to
fail—you should pass in a callback
that returns false. If a failure of
the query should cause the entire
transaction to fail, you should pass
in a callback that returns true.
For example if I have the following transaction (suppose the 'users' table has a UNIQUE constraint on the 'username' field and username 'test' already exists - which I'm trying to insert again, which should result in a constraint error):
database.transaction(function(transaction) {
transaction.executeSql(
"INSERT INTO users (username) VALUES('test')",
null,
dataCallback,
errorCallback
);
});
function errorCallback() {
return true; //this causes the rollback
}
I have two questions:
-
If I have to include many operations inside a transaction (for example I have to send some data using ajax to a server and wait for the response, etc.) and the user reloads the page before the response had arrived (which means that the errorCallback won't be called), will the transaction be commited or will it fail ?
-
Does anyone know how to rollback a Web SQL transaction manually ? For example if I want to rollback a transaction based on the result of an ajax call, how can it be done ? Should I run a query which contains an error to make sure that the error callback is called ?
Thanks.
发布评论
评论(2)
abort
方法。对于 AJAX,请在开始写入事务之前准备好所有数据。正如你所描述的,你不会有任何问题。尽可能使用数据库约束(UNIQUE、FOREIGNKEY)。
abort
method.Regarding AJAX, be ready all data, before you start a write transaction. You won't have any problem as you described. Use database constraint (UNIQUE, FOREIGNKEY) as much possible.
您是否找到了在交易期间进行 AJAX 调用的方法?我还没有读完整个规范,但到目前为止,一旦您的
SQLTransactionCallback
或SQLTransactionSyncCallback
返回,您就无法向事务添加更多内容 - 或者你可以吗?也许来自结果回调?编辑:
现在我再次查看规范(其中包含的错误比您链接到的 Apple 文档少得多,但不那么容易阅读)这样说:
所以我认为这意味着没有办法做到这一点。
进一步编辑:不,等等!只要
SQLStatementCallback
需要一些时间来调用,您就可以一次又一次地忙碌等待select 3 + 4
从前面的select 3 + 4
的语句回调开始,直到您的 AJAX 调用在包含您想要的数据的某个位置设置了一个标志。这是糟糕的编程(它会无缘无故地消耗大量 CPU,可能会阻止低优先级任务,例如重新显示页面),但我认为这可能是在任意时间段内保持事务打开的唯一方法。遗憾的是,您无法在 SQLite 中select 3 + 4, sleep(1)
。一般来说,SQLite(此处的底层存储引擎)会回滚未完成的事务。我尚未测试您所询问的页面重新加载错误情况。如果它被承诺,我会感到非常惊讶。
顺便说一句,非常感谢您提出这个问题。我一直在试图弄清楚如何让事务回滚,尽管它是精心设计的记录在原始规范中。
Have you found a way to do AJAX calls during the transaction? I haven't finished reading the whole spec, but so far it looks like once your
SQLTransactionCallback
orSQLTransactionSyncCallback
returns, you can’t add any more stuff to the transaction — or can you? Maybe from the results callback?Edit:
Now that I look again, the spec (which contains many fewer errors than the Apple document you linked to, but is not as easy to read) says this:
So I think that means there's no way to do it.
Further edit: No, wait! As long as the
SQLStatementCallback
takes some time to get called, you could busy-wait doingselect 3 + 4
over and over again, each time from the statement callback of the previousselect 3 + 4
, until your AJAX call sets a flag somewhere that has the data you want. This is terrible programming (it'll eat lots of CPU for no good reason, might block lower-priority tasks like redisplaying the page) but I think it's probably the only way to keep a transaction open for an arbitrary period of time. Too bad you can'tselect 3 + 4, sleep(1)
in SQLite.In general SQLite (the underlying storage engine here) rolls back uncompleted transactions. I haven’t yet tested the page-reload error case you're asking about. I would be very surprised if it was committed.
By the way, thank you very much for posting this question. I had been trying to figure out how to get the transaction to rollback, even though it is meticulously documented in the original spec.