添加到列表时是否具有类似Firebase transaction()的功能?

添加到列表时是否具有类似Firebase transaction()的功能?,firebase,Firebase,这是一个相当复杂的问题,但我会尽量简单明了地解释它 我正在使用Firebase构建一个多用户、基于web的游戏。我保留着游戏中每一轮的列表。在一轮结束时,每个用户都会看到一个“开始”按钮,当他们准备开始下一轮时,单击该按钮。当至少50%的用户单击“开始”时,该回合开始 我有一个游戏的Firebase参考gameRef,一个代表回合列表的参考roundListRef,还有一个代表当前回合的参考roundRef 我在roundListRef中附加了一个child\u added回调,以便在添加新一轮

这是一个相当复杂的问题,但我会尽量简单明了地解释它

我正在使用Firebase构建一个多用户、基于web的游戏。我保留着游戏中每一轮的列表。在一轮结束时,每个用户都会看到一个“开始”按钮,当他们准备开始下一轮时,单击该按钮。当至少50%的用户单击“开始”时,该回合开始

我有一个游戏的Firebase参考
gameRef
,一个代表回合列表的参考
roundListRef
,还有一个代表当前回合的参考
roundRef

我在
roundListRef
中附加了一个
child\u added
回调,以便在添加新一轮时,它将成为每个人的当前一轮:

roundListRef.on('child_added', function(childSnapshot, prevChildName) {
    roundRef = childSnapshot.ref();
});
我可以跟踪
newroundvoces
activePlayers
,并从中轻松计算出50%。如果达到50%,将添加新一轮,这将触发每个人的
child\u added
事件,新一轮将从那里开始

gameRef.child('newRoundVotes').on('value', function(snapshot) {
    var newRoundVotes = snapshot.val();

    gameRef.child('activePlayers').once('value', function(snapshot) {
        var activePlayers = snapshot.val();

        if (newDriveVotes / activePlayers >= 0.5)
            addNewRound();
    });
});
我的问题是,我如何确保只添加一个新回合,并且每个人都在同一轮

例如,假设有10名球员,4名已经投票开始下一轮比赛。如果第六名玩家在第五名玩家触发其添加的子项之前投票,则第六名玩家也将添加一轮

这个问题类似于
.set()
.transaction()
之间的问题,但据我所知并不完全相同


有人有解决方案吗?

我认为如果提前知道轮名,您可以通过事务解决这个问题。例如,如果您只使用/round/0、/round/1、/round/2等

然后您可以编写一些代码,如:

function addNewRound() {
    var currentRound = Number(roundRef.name());
    var nextRound = currentRound + 1;

    // Use a transaction to try to create the next round.
    roundRefList.child(nextRound).transaction(function(newRoundValue) {
        if (newRoundValue == null) {
            // create new round.
            return { /* whatever should be stored for the round. */ };
        } else {
            // somebody else already created it.  Do nothing.
        }
    });
}

这适用于您的场景吗?

您可以稍微修改您的想法,并使用圆形计数器作为跟踪并发性的场所

currentRound = 0;
currentRoundRef.on('value', function(snapshot) {
   currentRound = snapshot.val();
   roundRef = roundListRef.child(currentRound);
});

function addNewRound() {
    currentRoundRef.transaction( function(current_value) {
       if( current_value !== currentRound ) {
          // the round timer has been updated by someone else
          return;
       }
       else {
          return currentRound + 1;
       }
    }, function(success) {
       // called after our transaction succeeds or fails
       if( success ) {
          roundListRef.child(currentRound+1).set(...);
       }
    });
}

哈那就简单多了。我甚至没有想过你可以对一个还不存在的孩子使用
事务处理
。是的,它确实存在-好主意!我一直在使用push(),只是因为它是一个列表,我甚至没有想过要做类似的事情。谢谢