Javascript 边缘情况下的IndexedDb事务自动提交行为

Javascript 边缘情况下的IndexedDb事务自动提交行为,javascript,transactions,indexeddb,Javascript,Transactions,Indexeddb,在以下情况下提交Tx: 请求成功回调返回 -这意味着,只有在从上一个请求的成功回调执行下一个请求时,才能在事务边界内执行多个请求 当任务返回到事件循环时 这意味着,若并没有向其提交任何请求,则在返回到事件循环之前,不会提交该请求。这些事实造成了两个问题: 通过将新任务从上一个请求的成功回调中排队到事件循环队列来放置新的IDB请求,而不是同步提交新请求 在这种情况下,第一个成功回调立即返回,但另一个IDB请求已被调度 是否所有异步请求都在单个初始事务中执行?如果您想在背压的情况下实施结果

在以下情况下提交Tx:

  • 请求成功回调返回 -这意味着,只有在从上一个请求的成功回调执行下一个请求时,才能在事务边界内执行多个请求
  • 当任务返回到事件循环时
这意味着,若并没有向其提交任何请求,则在返回到事件循环之前,不会提交该请求。这些事实造成了两个问题:

  • 通过将新任务从上一个请求的成功回调中排队到事件循环队列来放置新的IDB请求,而不是同步提交新请求
    • 在这种情况下,第一个成功回调立即返回,但另一个IDB请求已被调度
      • 是否所有异步请求都在单个初始事务中执行?如果您想在背压的情况下实施结果拉动,而消费者以未来的形式向您提供反馈,准备使用另一个响应,则这一点非常重要
  • 创建读写tx,不对其放置任何请求,并在返回事件循环之前创建另一个
    • 创建新的发送是否隐式提交上一个发送?否则,可能会发生严重的写锁不足,因为:
如果多个“读写”事务试图访问同一个 对象存储(即,如果它们的作用域重叠),事务 首先创建的必须是获取访问权限的事务 对象首先存储。根据上一节的要求 这也意味着,这是唯一一项具有 在事务完成之前访问对象存储

通过带背压的递归请求提交将新任务从成功回调中排队到事件循环队列的示例:

    function recursiveFn(key) {
      val req = store.get(key)
      req.onsuccess = function() {
        observer.onNext(req.result).onsuccess { recursiveFn(nextKey) } 
      }
    }

Observer#onNext // returns Future[Ack] Ack is either Continue or Cancel
现在可以
onsuccess
onNext
执行设置超时(0)或不将整个事务作为一个事务的一部分吗

奖金问题:


我认为只读事务是向消费者/用户公开的,因为如果您递归地提交来自前一个成功回调的新请求,则很难检测到批读取的结束,对吗?否则,我看不出它们向用户公开的任何其他原因,对吗?

我不确定我是否完全理解您的问题,但我将提供一个关于您是否可以安全地使用IDB事务事件移动状态机的答案

是和否。理论上是,实践上不是

我想你了解这笔交易。但是:

事务的生命周期与被引用的时间一样长:只要被引用,它就处于“活动”状态,之后称为“完成”并提交事务

从理论上讲,
oncomplete
应该在事务成功提交时触发。关于这一点,有一个有用的提示,建议您如何循环:

要确定事务是否已成功完成,请侦听事务的complete事件,而不是IDBObjectStore.add请求的success事件,因为在成功事件触发后,事务仍可能失败

要安全地使用此机制,请确保监视非成功事件,包括
onblocked
onbort

实际上,我发现当事务长期存在或成批连续完成时(正如您在另一篇IDB评论中所指出的),事务会变得很脆弱。我通常不会设计我的应用程序来要求复杂的行为,因为无论规范如何规定它应该如何行为,我都会在Firefox和Chromium中看到不稳定的事务(但有趣的是,大多数都会闪烁),特别是当多个选项卡打开时

我花了数周时间重写事务,以重用事务,从而获得预期的性能提升。最后,它甚至无法通过我的基本写测试,我被迫放弃同步/排队/连续事务,并再次重写。这次我选择了一次一个事务的模型,它速度较慢,但对我来说更可靠(建议避免使用lib,并使用类似ydn的东西进行批量插入)


我不确定您的应用程序需求,但在我看来,将I/O绑定到事件循环似乎是一个灾难性的想法。如果我需要一个事件循环,正如我所理解的那样,我肯定会使用
requestAnimationFrame()
,如果我需要少于每33毫秒一次的滴答声,我会阻止回调。

你能添加到indexeddb规范的适当链接吗?我没有,这是我的想法和过去几周对IndexedDb的丰富经验。顺便说一句,IndexedDb开发人员回答了很多问题,我在这里强调了最重要的部分。我需要知道的是,我是否可以在不提交事务的情况下在成功回调中执行
setTimeout(0)
。或者
setTimeout(0)
是否使事务被提交?我们不要考虑背压问题。我只是想知道我是否可以在一个事务内成功回调中安排(
setTimeout(0)
)以下递归请求。。。“灾难性的想法”你是指我说的吗?在成功回调中不应该递归地
setTimeout(0)