代码之家  ›  专栏  ›  技术社区  ›  Lahiru Chandima

Firebase实时数据库事务处理程序在大多数情况下会被调用两次

  •  0
  • Lahiru Chandima  · 技术社区  · 5 年前

    我正在使用我的nodejs应用程序中的firebase admin 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);
    });
    

    我可以观察到这一点 transaction handler got called 为上述代码的每次执行记录两次。

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

    有人知道这是什么原因吗?

    0 回复  |  直到 5 年前
        1
  •  4
  •   Frank van Puffelen    5 年前

    这是预期的行为。当您运行事务时,Firebase客户端立即调用您的事务处理程序,并对当前的 some/path . 第一次运行它时,最好的猜测通常是 null 一些/路径 已经存在,但总是错误的,并且在客户端具有正确的当前值后,将始终导致对事务处理程序的第二次调用。

     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       |
                  |<-----------------------+|
                  |                         |
                  +                         +
    

    另请参见以下关于事务如何工作的解释: