【问题标题】:Why is my data storing twice in my Firebase Database?为什么我的数据在 Firebase 数据库中存储了两次?
【发布时间】:2020-07-11 20:35:56
【问题描述】:

我是使用 Firebase 的新手,因此欢迎所有建议。

我想要达到什么目的?

我只想在用户没有超过他们的团队规模(“numberOfplayersLimit”)的情况下创建一个玩家。 所以目前我正在使用一个firebase事务,它首先检查团队没有超过他们的限制“numberOfPlayers”,如果团队没有超过他们的限制,增加“numberOfplayersLimit”计数器,然后将玩家添加到数据库中,如下所示。

我的问题是什么

我目前正在使用.push() 添加播放器,但是它创建了两次播放器,如下所示,因为您可以看到其他记录中的全名相同,但它们具有不同的 uid。

下面是我的 Firebase 实时数据库 JSON 结构的截图

var myUserId = firebase.auth().currentUser.uid;
    
const playerData = {
    fullName:this.state.fullName,
   
};

 //This is where the players are stored 
 const teamplayersref = firebase.database().ref('/teams').child(myUserId).child('/players')


 //Transaction - Team reference path for the TeamPlayers Limit
 const getTeamPlayersLimit = firebase.database().ref('/teams').child(myUserId).child('numberOfplayersLimit');

  getTeamPlayersLimit.transaction(function(numberOfplayersLimit){


        if (numberOfplayersLimit == 11) {
            alert('You have exceed your team size limit, Delete a player from your team or contact us to upgrade your package');
        }

        else 
        {
          
            //increment teamplayers limit
            numberOfplayersLimit = numberOfplayersLimit + 1;
              
 
            teamplayersref.push(playerData);
 
            return numberOfplayersLimit;

        }
    });

【问题讨论】:

  • 在事务处理程序中放置一个 alert() 不是一个好主意。相反,您应该使事务失败,并在完成后发出警报。还要记住,事务处理程序可能会被调用多次(以 null 作为数据库中的值开始),并且通常应该只修改事务所在位置的数据。我建议添加一些日志以查看实际发生的情况。
  • 您不应检查numberOfplayersLimit == 11,而应检查numberOfplayersLimit >= 11。这包括 11 及以上的任何东西。第一个确实只包含 11。
  • @DougStevenson 递增不是问题,因为它增加了一个,这是正确的。问题是当我使用 .push() 时,它会创建两次播放器。您建议记录什么?
  • @Simon 感谢您的帮助,但我现在已经在那里尝试过了,我的问题仍然存在
  • 在事务句柄中记录任何内容以查看它是如何执行的。使用调试来跟踪其执行。 push() 被调用了两次,我的第一条评论是给你原因 - 处理程序被调用了两次。

标签: javascript firebase react-native firebase-realtime-database


【解决方案1】:

事务处理程序中的teamplayersref.push(playerData) 调用不是事务本身的一部分。因此,如果重试事务,您最终会多次调用teamplayersref.push(playerData),为每次尝试创建一个子节点。

要生成具有唯一推送 ID 的新子代,请使用不带参数的推送来获取新密钥,然后在您的事务的 return 值中使用该密钥。这意味着您的事务必须在整个 firebase.database().ref('/teams') 节点上运行,因为您正在修改计数器和播放器。

const teamRef = firebase.database().ref('/teams').child(myUserId);

teamRef.transaction(function(team){
    team = team || { numberOfplayersLimit: 0, players: {} };
    if (team.numberOfplayersLimit == 11) {
        console.error('You have exceed your team size limit, Delete a player from your team or contact us to upgrade your package');
    }
    else  {
        team.numberOfplayersLimit = team.numberOfplayersLimit + 1;
        const newPlayerKey = teamRef.push().key; // this line does not write to the database

        team.players[newPlayerKey] = playerData;

        return team;
    }
});

【讨论】:

  • 您好,感谢您的回答。我看到一个错误“TypeError: Cannot read property 'numberOfplayersLimit' of null”。它出现在 if 语句开始的那一行
  • 在这种情况下,team 似乎不存在,因此您需要检查一下。老实说,我没有测试就写了这个,所以它可能包含一些小错误,并且可能会错过这样的错误处理。
  • 不幸的是,.push() 仍在存储两次。如果我使用 const getTeamPlayersLimit = firebase.database().ref('/teams').child(myUserId).child('numberOfplayersLimit');而不是您的解决方案参考?
  • 我的代码读取整个团队的 JSON,并对其进行修改。它不应该创建多个节点。你确定teamRef.transaction() 只被调用一次吗?在它可能显示之前添加一个console.log
  • 所以当我 console.log(numberOfplayersLimit);第一个值为空,然后递增到新值。这可能是它创建播放器实例的原因
猜你喜欢
  • 2018-10-04
  • 1970-01-01
  • 2015-06-20
  • 1970-01-01
  • 1970-01-01
  • 2018-07-28
  • 1970-01-01
  • 2021-08-14
  • 2018-10-28
相关资源
最近更新 更多