我正在使用事务写入Firebase实时数据库中的特定位置,在我的nodejs应用程序中使用Firebase admin api。我观察到事务处理程序被调用两次,即使没有其他客户端使用数据库。
下面是显示此行为的最小代码。
firebaseAdmin.database().ref('some/path').transaction(currentData => {
console.log('transaction handler got called');
return {'abc': 'def'};
}, null, false).then(value => {
console.log('transaction complete')
}).catch(reason => {
console.log('transaction failed. ' + reason);
});
我可以观察到,每次执行上述代码都会记录两次transaction handler got called
。
我知道,如果在读取事务currentData
和尝试将新数据提交到数据库路径之间,其他客户端写入窗口中的数据库路径,则处理程序可能会被多次调用。但是,在我的情况下没有其他客户端,所以我不明白为什么事务处理程序需要被调用两次。
有谁知道这是什么原因?
预期行为。当您运行事务时,Firebase 客户端会立即调用您的事务处理程序,并尽可能猜测当前值 some/path
。第一次运行它时,此最佳猜测通常是null
。如果some/path
已经存在,则始终是错误的,并且一旦客户端具有正确的当前值,将始终导致对事务处理程序的第二次调用。
在流程图中,它看起来像这样
app code client server
+ +
transaction() | |
|+--+ |
| |current == null |
| v |
| |new = 0 |
|<--+ |
| |
| current==null, new=0 |
|+----------------------->|
| |+--+
| | |current != null
| | v
| | |current = 0
| |<--+
| NACK, current=0 |
|<-----------------------+|
| |
|+--+ |
| |curent==0 |
| v |
| |new=1 |
|<--+ |
| |
| current==0, new=1 |
|+----------------------->|
| |+--+
| | |current == 0
| | v
| | |current = 1
| |<--+
| ACK, current=1 |
|<-----------------------+|
| |
+ +
另请参阅以下有关事务工作原理的说明:
- Firebase runTransaction 不起作用 - 可变数据为空
- 火力基地交易的奇怪行为
- 安卓Firebase数据库事务