请参阅 jsbin.com/ceyiqi/edit?html,console,output 以获取可验证的示例。
我有一个监听数据库点的引用
工作/<key>
/列表
哪里<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
事件,那么您将看到:
- 初始值
- null(当事务启动并在
null
上运行时) - 再次初始值(当交易在真实数据上再次运行时)
步骤 2 中的 null
值是客户端对当前值的初始猜测。由于客户端没有/jobs 的缓存数据(它忽略/jobs/list 的缓存数据),因此猜测为 null。这显然是错误的。但不幸的是这种情况已经存在很长时间了,因此在当前的 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 中改变这种行为。
关于javascript - Firebase Web SDK - 事务导致 ('child_added' 、 func.. 被调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39110154/