Firebase Web SDK -事务导致on('child_added', function).等待

Firebase Web SDK - Transaction causing on('child_added', func.. to be called

本文关键字:added child function 等待 Web SDK 事务 on Firebase      更新时间:2023-09-26

请参见jsbin.com/ceyiqi/edit?html,console,output查看可验证的示例。

我有一个参考监听数据库点

jobs/<key>/list

其中<key>为队伍唯一编号

在这个入口点下面是一个作业列表

在这一点上我有一个听众

this.jobsRef.orderByChild('archived')
                    .equalTo(false)
                    .on('child_added', function(data) {

我还有一个方法执行以下事务:

ref.transaction(function(post) {
    // correct the counter
    if(post)
    {
        // console.log(post);   
        if(active)
        {
            // if toggeling on
        }
        else
        {
            // if toggeling off
        }
    }
    return post;
})

当调用事务时,child_added也被再次调用,给我重复的作业。

这是预期行为吗?我是否应该简单地检查项目之前是否已经获得并相应地添加到数组中?还是我做错了什么?

提前感谢您的时间

您在Firebase客户端如何处理事务方面遇到了一个有趣的边缘情况。事务函数运行两次,首先在null上运行,然后在实际数据上运行。很明显,如果您侦听/jobs上的value事件,那么您将看到:

  1. 初始值
  2. null(当事务在null上启动和运行时)
  3. 初始值(当事务在真实数据上再次运行时)

步骤2中的null值是客户端对当前值的初始猜测。由于客户端没有/jobs的缓存数据(它忽略了/jobs/list的缓存数据),因此它猜测为空。这显然是错误的。但不幸的是,这种情况已经持续了很长时间,所以在当前SDK的主要版本中不太可能改变。

并且由于步骤2中的null,您将获得child_removed事件(您现在没有处理),然后在步骤3中您将获得child_added事件以重新添加它们。

如果你处理了child_removed事件,你的物品最终不会重复,但它们仍然会消失/重新出现,这可能是不可取的。当前设置中的另一个解决方案是显式地告诉事务不要使用本地估计运行,可以通过将false作为第三个参数传入来实现:

function transact() {
    var path = 'jobs/';
    var ref = firebase.database().ref(path);
    ref.transaction(function(post) {
      return post;
    }, function(error, committed, snapshot) { 
      if (error) {
        console.log('Transaction failed abnormally!', error);
      } else if (!committed) {
        console.log('Transaction aborted.');
      } else {
        console.log('Transaction completed.');
      }
    }, false);
}
对不起,我没有更好的解决办法。但正如我所说的:我们不太可能在当前这一代sdk中改变这种行为。