这是一件相当奇怪的事情,很难再现。不是错误报告的最佳状态,我道歉。
我使用.transaction()将值写入Firebase中的某个位置。这是一些伪代码:
var ref = firebase.child('/path/to/location');
var storeSafely = function(val) {
ref.transaction(
function updateFunc(currentData) {
console.log('Attempting update: ' + JSON.stringify(val));
if (currentData) return;
return val;
},
function onTransactionCompleteFunc(err, isCommitted, snap) {
if (err) {
console.log('Error in onTransactionCompleteFunc: ' + JSON.stringify(err));
return;
}
if (! isCommitted) {
console.log('Not committed');
return;
}
ref.onDisconnect().remove();
doSomeStuff();
});
};
var doSomeStuff = function() {
// Things get done, time passes.
console.log('Cleaning up');
ref.onDisconnect().cancel();
ref.set(
null,
function onSetCompleteFunc(err) {
if (err) {
console.log('Error in onSetCompleteFunc: ' + JSON.stringify(err));
}
});
};
storeSafely(1);
// later...
storeSafely(2);
// even later...
storeSafely(3);
我有效地使用Firebase交易作为一种互斥锁:
通过交易将值存储在某个位置。
设置该位置的onDisconnect,以便在我的应用程序在工作时死亡时删除该值。
做一些事情。
删除该位置的onDisconnect,因为我已经完成了这些工作。
删除该位置的值。
我每隔几分钟就做一次,这一切都很棒。事情得到了完美的编写和删除,日志显示我创建锁定,执行操作,然后释放锁定。
奇怪的部分是小时之后发生的事情。偶尔Firebase有维护,我的应用程序获得了一堆权限被拒绝的错误。在这种情况发生的同时,我突然开始在日志中获得一堆这样的输出:
Attempting update 1
Attempting update 2
Attempting update 3
......换句话说,看起来交易从未完全完成,并且他们现在正在尝试重试该位置无法再读取。它几乎就像在事务()代码中的闭包从未完成,并且由于某种原因它现在被重新执行。
我是否遗漏了一些关于如何结束交易的重要内容?
(注意:我最初将此帖子发布到Firebase Google Group,但最终提醒代码问题应该转到Stack Overflow。我为交叉发布道歉。)
答案 0 :(得分:0)
只是一个猜测,但我想知道当您的应用从Firebase获得权限拒绝错误时,是否使用updateFunc()
调用了您的null
功能。 (如果是这样,我可以相信这是他们“离线写作”支持的一部分。)
在任何情况下,您都应该将null
作为可能的状态处理。 Saving Transactional Data说:
transaction()
将被多次调用,并且必须能够处理null
数据。即使数据库中存在现有数据,也可能没有 在运行事务函数时本地缓存。
我不知道Firebase的交易机制的复杂性,但我会尝试更改您的.set(null)
以将值设置为0
,而是更改您的.remove()
以设置值使用.set(0)
,并将updateFunc()
中的行更改为:
if (currentData === null || currentData) return;
不幸的是,这假设'/path/to/location'
最初在某个时候设置为0
。如果这是一个问题,也许你可以使用null
与undefined
混在一起。例如,如果Firebase使用其中一个用于不存在的数据而另一个用于脱机数据,则会很好。