事务中的数据为空

时间:2015-03-02 13:31:01

标签: firebase

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

  

要实现此目的,您将传递transaction()一个更新函数   用于将当前值转换为新值。如果另一个   客户端在新值成功之前写入该位置   写完后,您的更新功能将再次使用new调用   当前值,将重试写入。这将发生   反复,直到你的写作成功没有冲突或你中止了   通过不从更新函数返回值来进行事务

现在我知道现在没有其他客户端访问该位置。其次,如果我正确阅读文档,如果无法检索和更新数据,则应多次调用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);

这是位置

中的数据
counters:{
  comments: 1,
  alerts: 3,
  ...
}

1 个答案:

答案 0 :(得分:21)

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

事实证明,committedfalse且成功函数中的错误为null,如果事务中止,则会出现错误。

交易的工作方式如下:

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

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

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