Firebase 实时数据库事务处理程序大部分时间都会被调用两次

Lah*_*ima 5 node.js firebase firebase-realtime-database

我正在使用我的 Nodejs 应用程序中的 Firebase 管理 api 使用事务写入 Firebase 实时数据库中的特定位置。我观察到,即使没有其他客户端使用该数据库,事务处理程序也会被调用两次。

以下是显示此行为的最小代码。

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);
});
Run Code Online (Sandbox Code Playgroud)

我可以观察到transaction handler got called每次执行上述代码都会被记录两次。

currentData据我了解,如果其他客户端写入事务读取窗口中的数据库路径,并且尝试将新数据提交到数据库路径,则处理程序可能会被多次调用。但是,在我的例子中没有其他客户端,所以我无法理解为什么事务处理程序需要被调用两次。

有谁知道这是什么原因?

Fra*_*len 6

这是预期的行为。当您运行事务时,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       |
              |<-----------------------+|
              |                         |
              +                         +
Run Code Online (Sandbox Code Playgroud)

另请参阅以下有关交易如何运作的说明:

  • 那么为什么 sdk 不只在知道来自服务器的正确值后才调用处理程序呢?我认为在不知道正确值的情况下调用处理程序没有任何意义,因为一旦从服务器获取了正确的值,它无论如何都必须再次调用处理程序。 (2认同)