事务中的数据为空

web*_*vet 6 firebase

我的交易有问题.事务中的数据始终为null,并且更新处理程序仅调用一次.该文件说:

为此,您将传递transaction()一个更新函数,该函数用于将当前值转换为新值.如果另一个客户端在成功写入新值之前写入该位置,则将使用新的当前值再次调用更新函数,并将重试写入.这将反复发生,直到您的写入成功而没有冲突,或者您通过不从更新函数返回值来中止事务

现在我知道现在没有其他客户端访问该位置.其次,如果我正确阅读文档,如果无法检索和更新数据,则应多次调用updateCounters函数.

另一件事 - 如果我取出条件if (counters === null),执行将失败,因为计数器是null在随后的尝试中事务完成 - 检索数据并进行更新.

简单的once - set在这个位置工作很好,但它不安全.

请问我错过了什么?

这是代码

self.myRef.child('counters')
  .transaction(function updateCounters(counters){
    if (counters === null) {
      return;
    }
    else {
      console.log('in transaction counters:', counters);
      counters.comments = counters.comments + 1;
      return counters;
    }
  }, function(error, committed, ss){
    if (error) {
      console.log('transaction aborted');
      // TODO error handling
    } else if (!committed){
      console.log('counters are null - why?');
    } else {
      console.log('counter increased',ss.val());
    }
  }, true);
Run Code Online (Sandbox Code Playgroud)

这是该位置的数据

counters:{
  comments: 1,
  alerts: 3,
  ...
}
Run Code Online (Sandbox Code Playgroud)

Kat*_*ato 21

通过undefined在您的if( ... === null )区块中返回,您正在中止交易.因此,它永远不会向服务器发送尝试,永远不会意识到本地缓存的值与远程不同,并且永远不会重试更新的值(来自服务器的实际值).

这是由事实证实committedfalse与错误是null在你的成功的功能,如果交易被中止发生.

交易工作如下:

  • 将本地缓存的值传递给处理函数,如果您从未从服务器获取此数据,则本地缓存的值null(该路径的最可能远程值)
  • 从处理函数获取返回值,如果该值undefined中止事务,否则,创建当前值的哈希值(null)并将该值和新值(由处理函数返回)传递给服务器
  • 如果本地哈希与服务器的当前哈希匹配,则应用更改并且服务器返回成功结果
  • 如果未应用服务器事务,则服务器返回新值,然后客户端再次使用服务器的更新值调用处理函数,直到成功为止
  • 当最终成功,发生不可恢复的错误,或者事务中止(通过从处理函数返回undefined)时,将使用结果调用success方法.

所以为了使这项工作,显然你不能在第一个返回值上中止事务.

实现相同结果的一种解决方法 - 虽然它是耦合的,而不是仅仅使用设计的事务的once('value', ...)高效或适当 - 将事务包装在回调中,这将确保在运行事务之前在本地缓存它.