首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在云功能事务中检索和分配gameId给多个参与者

在云功能事务中检索和分配gameId给多个参与者
EN

Stack Overflow用户
提问于 2020-10-23 23:10:22
回答 1查看 81关注 0票数 0

我一直在跟踪这个教程,并试图在游戏中添加第三个玩家。下面是为两位玩家工作的源代码。以下是我的数据结构:

代码语言:javascript
复制
  "matchmaking" : {
    "32idNK8OndcujN8CFNe3VBTxsXL2" : {
      "gameId" : "placeholder"
    },
    "LnMnOtdLJYbsRuTeUpeHfaAhpX32" : {
      "gameId" : "placeholder"
    },
    "plpISHWWtuNJvhSlFwfik6DOHR53" : {
      "gameId" : "placeholder"
    }
  }

我有一个云函数,每当用户加入婚介室时,都会调用它。根据可用的两个用户的不同,该功能为所有三个用户生成一个独特的游戏室。我对Javascript不太熟悉,所以我已经在这方面挣扎了一段时间。

如何在事务期间检索gameId值并将其分配给三个参与者?

代码语言:javascript
复制
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);

var database = admin.database();

exports.matchmaker = functions.database.ref('matchmaking/{playerId}')
    .onCreate((snap, context) => {

        var gameId = generateGameId();

        database.ref('matchmaking').once('value').then(snapshot => {
            var secondPlayer = null;
            var thirdPlayer = null;           
            
            // add two players into the queue 
            snapshot.forEach(child => { // check that its not the playerId who just joined  
                var playerId = child.key
                var gameId = child.val().gameId
                if (gameId === "placeholder" && playerId !== context.params.playerId) {
                    secondPlayer = child; 
                }             
            });         

            snapshot.forEach(child => { // check that its not the playerId who just joined 
                var playerId = child.key
                var gameId = child.val().gameId             
                if (gameId === "placeholder" && playerId !== secondPlayer.key && playerId !== context.params.playerId) {
                    thirdPlayer = child; 
                }                
            });            

            if (secondPlayer === null || thirdPlayer === null) return null; // one room needs three players                     
          
            database.ref("matchmaking").transaction(function (matchmaking) {

                console.log(matchmaking)                
                
                // ================================================ 
                // PROBLEM STARTS HERE
                // ================================================ 
                
                console.log("playerId gameId:",context.params.playerId.gameId)  // returns undefined                
                
                // If any of the players gets into another game during the transaction, abort the operation
                if (matchmaking === null || 
    context.params.playerId.gameId !== "placeholder" ||
    matchmaking[secondPlayer.key].gameId !== "placeholder" || 
    matchmaking[thirdPlayer.key].gameId !== "placeholder") return matchmaking; 


             //    matchmaking.forEach(player => { // check that its not the playerId that just joined  
                //  var playerId = player.key
                //  var gameId = player.val().gameId
                //     if (gameId !== "placeholder") {
                //      player["gameId"] = gameId;
                //     }             
                // });                    

                context.params.playerId.gameId = gameId; // assign game id to player 
                matchmaking[secondPlayer.key].gameId  = gameId; 
                matchmaking[thirdPlayer.key].gameId = gameId;
                return matchmaking;

            }).then(result => {

                if (result.snapshot.child(context.params.playerId).val() !== gameId) return;

                // ENDS HERE
                // ================================================ 

                var game = {
                    gameInfo: {
                        gameId: gameId,
                        playersIds: [context.params.playerId, secondPlayer.key, thirdPlayer.key]
                    },
                    turn: context.params.playerId
                }

                database.ref("games/" + gameId).set(game).then(snapshot => {

                    console.log("Game created successfully!")
                    return null;
                }).catch(error => {
                    console.log(error);
                });

                return null;

            }).catch(error => {
                console.log(error);
            });

            return null;
        }).catch(error => {
            console.log(error);
        });
    });

function generateGameId() {
    var possibleChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    var gameId = "";
    for (var j = 0; j < 20; j++) gameId += possibleChars.charAt(Math.floor(Math.random() * possibleChars.length));
    return gameId;
}

我收到了一些错误,比如matchmaking.forEach is not a functionCannot read property 'params' of undefinedCannot read property 'val' of undefined

Console.log(婚介)显示如下:

代码语言:javascript
复制
{ '32idNK8OndcujN8CFNe3VBTxsXL2': { gameId: 'placeholder' },
  LnMnOtdLJYbsRuTeUpeHfaAhpX32: { gameId: 'placeholder' },
  plpISHWWtuNJvhSlFwfik6DOHR53: { gameId: 'placeholder' } } 

我真的很感谢你的帮助。

更新:

解决方案:

代码语言:javascript
复制
            database.ref("matchmaking").transaction(function (matchmakingSnapshot) {

                if (matchmakingSnapshot) {                      
                    matchmakingSnapshot[context.params.playerId].gameId = gameId; // assign game id to player 
                    matchmakingSnapshot[secondPlayer.key].gameId  = gameId; 
                    matchmakingSnapshot[thirdPlayer.key].gameId = gameId;
                    return matchmakingSnapshot;     
                } else if ( // If any of the players gets into another game during the transaction, abort the operation
                    matchmakingSnapshot === null || 
                    context.params.playerId.gameId !== "placeholder" ||
                    matchmakingSnapshot[secondPlayer.key].gameId !== "placeholder" || 
                    matchmakingSnapshot[thirdPlayer.key].gameId !== "placeholder") {
                    return matchmakingSnapshot;    
                }                   

            }).then(result => {

问题是,当我试图更新gameId时,事务返回一个空数据。在访问上下文参数matchmaingSnapshot之前,我必须确保playerId不是null。我不知道为什么调用matchmakingSnapshot.val()返回未定义的函数,但就是这样!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-10-23 23:18:57

您目前不应该得到错误matchmaking.forEach is not a function

".forEach“函数可以在数组或DataSnapshot上工作(在子程序上迭代,依次提供每个子程序的DataSnapshot )。

但是,如果您有一个对象,".forEach“将提供您描述的错误消息。目前的代码似乎有“匹配”作为一个DataSnapshot,因此,它应该是".forEach“的时候。

错误说明:无法读取未定义的属性“params”

我认为您不小心插入了变量名,而不是告诉javascript使用变量名的值

代码语言:javascript
复制
if (matchmaking === null || 
    matchmaking.context.params.playerId.gameId !== "placeholder" ||
    matchmaking.secondPlayer.key.gameId !== "placeholder" || 
    matchmaking.thirdPlayer.key.gameId !== "placeholder"
) return matchmaking; 

我想你不是指matchmaking.secondPlayer.key.gameId。我认为你指的是matchmaking[secondPlayer].key.gameId,所以如果secondPlayer是"ABC123",你指的是matchmaking.ABC123.key.gameId

thirdPlayer也一样。

错误说明:无法读取未定义的属性“params”

你是说只有context.params.playerId.gameId而不是matchmaking.context.params.playerId.gameId?你可能是错误地添加了“婚介”?

探索错误: TypeError:无法读取未定义的属性“gameId”

如果您从以下内容中得到上述错误:

代码语言:javascript
复制
matchmaking[context.params.playerId].key.gameId` 

首先,检查是否需要步骤".key“。看一下您的对象,在我看来,".gameId“直接出现在matchmakingplayerId之后,不需要".key”。如果您确信您需要".key",那么我将按照以下方式进行调试。在该语句之前插入以下控制台日志。

代码语言:javascript
复制
console.log("playerId:",context.params.playerId)
console.log("matchmaking[context.params.playerId]:", 
    matchmaking[context.params.playerId])

然后检查一下playerId是否是明智的。如果不是,则将整个上下文console.log为

代码语言:javascript
复制
console.log("context:",JSON.stringify(context)) // This avoids getting something useless logged like `[Object object]`.

如果playerId是正确的,那么您将看到matchmaking是否有该播放器的条目。这种调试方法最终会暴露问题的所在。

我认为最后一个问题是“匹配”( DataSnapshot )和简单的、可写的对象之间的混淆。

这对我来说很难理解,因为婚介目前是一种DataSnapshot,这是一种有点令人困惑的东西。它似乎得到了console.logged,好像它是一个对象,但它是不可写的。

我建议我们提取一个实际的对象如下:

代码语言:javascript
复制
database.ref("matchmaking").transaction(function (matchmaking) {
    let matchmakingObject = matchmaking.val();

    // ... remainder of code as before, and then:

    matchmakingObject[context.params.playerId.gameId] = gameId; // assign game id to player 
    matchmakingObject[secondPlayer.key].gameId  = gameId; 
    matchmakingObject[thirdPlayer.key].gameId = gameId;
    return matchmakingObject;

我希望这能解决问题!

我避免这种问题的方法是总是调用快照xxxxSnapshot。这样,我永远不会忘记,虽然它可能console.log,好像它是一个物体,但在现实中,它是某种神秘的东西。

例如,如果我正在编写这段代码,我将按如下方式调用:

代码语言:javascript
复制
database.ref("matchmaking")
.transaction(function (matchmakingSnapshot) {
    let matchmakingObject = matchmakingSnapshot.val();

    // ... remainder of code as before, and then:

    matchmakingObject[context.params.playerId.gameId] = gameId; // assign game id to player 
    matchmakingObject[secondPlayer.key].gameId  = gameId; 
    matchmakingObject[thirdPlayer.key].gameId = gameId;
    return matchmakingObject;

它有点丑陋,但比尝试调试一个具有两个非常不同的含义,很容易混为一谈的名称更痛苦。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64508339

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档