我的交易有问题。事务中的数据始终为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,
...
}
答案 0 :(得分:21)
通过在undefined
块中返回if( ... === null )
,您正在中止交易。因此它永远不会向服务器发送尝试,永远不会意识到本地缓存的值与远程不同,并且永远不会重试更新的值(服务器的实际值)。
事实证明,committed
为false
且成功函数中的错误为null
,如果事务中止,则会出现错误。
交易的工作方式如下:
null
(该路径最可能的远程值)undefined
则中止事务,否则,创建当前值的哈希值(null)并传递该值和新值(由处理函数返回)到服务器为了使这项工作,显然你不能在第一个返回值上中止事务。
实现相同结果的一种解决方法 - 虽然它是耦合的,而不是仅仅使用设计的事务的高效或适当 - 将事务包装在once('value', ...)
回调中,这将确保它的在运行事务之前在本地缓存。