从firebase函数返回数据时返回空值

nom7f22z  于 2022-11-25  发布在  其他
关注(0)|答案(1)|浏览(154)

我有这个密码

exports.battle = functions.https.onCall((data, context) => {
    if(context.auth){
        var difficulty = randInt(2,10) / 10
        var user = context.auth["uid"]
        
        var userHP
        var userLevel
        var userDmg 
        var resultUserDmg = []
        var resultUserHp = []

        var monsterHP
        var monsterLevel
        var monsterDmg
        var resultMonsterDmg = []
        var resultMonsterHp = []

        

        var ref = db.ref(`players/${user}`);
        ref.child("hp").once("value", (snapshot) => {
           userHP = snapshot.val()
           monsterHP = userHP * difficulty

           ref.child("level").once("value", (snapshot) => {
                userLevel = snapshot.val()
                monsterLevel = userLevel * difficulty

                console.log("type"+typeof(userHP))
                console.log("value"+userHP)
                

                console.log("type"+typeof(monsterHP))
                console.log("value"+monsterHP)
                console.log("diff "+difficulty)

                while (userHP > 0 && monsterHP > 0){
                    userDmg = randInt(7, 14) * userLevel
                    monsterDmg = randInt(7, 14) * userLevel * difficulty

                    userHP = Math.round((userHP - monsterDmg)*10) /10;
                    console.log("userHP"+(userHP))
                    console.log("monsterDmg"+monsterDmg)
                    resultMonsterDmg.push(Math.round(monsterDmg*10) /10)
                    resultUserHp.push(Math.round(userHP*10)/10)
                    monsterHP = Math.round((monsterHP - userDmg)*10) /10;
                    console.log("userDmg"+userDmg)
                    console.log("monsterHP"+monsterHP)
                    resultUserDmg.push(Math.round(userDmg*10)/10)
                    resultMonsterHp.push(Math.round(monsterHP*10)/10)
                    console.log("----------")
                }

            
                var ref = db.ref(`players/${user}/coins`);
                ref.once("value", function(snapshot) {
                    var coinsNow = parseInt(snapshot.val());
                    const userRef = db.ref(`players/${user}`);
                    userRef.update({
                        'coins' : coinsNow+1
                    })
                });

                var result ={
                    userDmg : resultUserDmg,
                    userHp : resultUserHp,
                    monsterDmg : resultMonsterDmg,
                    monsterHp : resultMonsterHp,
                    monsterLvl : monsterLevel,
                };
                console.log("result is "+resultUserDmg)
                console.log("result is "+resultUserHp)
                console.log("result is "+resultMonsterDmg)
                console.log("result is "+resultMonsterHp)
                console.log("result is "+monsterLevel)
                return result 

            })
        })
    }
    else{
        console.log("User is not logged")
    }

    
})

简单来说,这段代码的作用是通过while循环计算玩家的生命值和对怪物造成的伤害。这是正确的。问题是当我想把result变量中的数据发送给用户做进一步的工作时。它每次都返回null。你知道错误在哪里吗?我唯一能想到的是错误应该在返回中。也许在请求的数据有任何价值之前它就被调用了。我不知道。我想不通。
但是我确信我想发送给用户的值不是null,而是应该具有的值。
Firebase console log
这是我用于客户端返回的代码。我总是在这里得到null

var battle = firebase.functions().httpsCallable('battle')
    battle().then(result => {
        console.log(result)
    })

我只是在代码的开头更改了此内容,并在结尾添加了此内容

exports.battle = functions.https.onCall((data, context) => {
    if(context.auth){
         return new Promise(function(resolve, reject) {
                
                 /* 
                   . . . .                       
                     code 
                   . . . .
                            */

                 reslove(result)
)}

我建议在代码末尾添加.catch以防止可能出现的错误,但我不完全确定,所以我不想混淆

lb3vh1jj

lb3vh1jj1#

Promises的结果会出现在调用者那里,但前提是你必须在thencatch回调中返回它们。因此,在每个once回调中,你都需要确保将值return返回给调用者。
首先,您在顶级Cloud函数中缺少一个顶级return语句,这意味着您的return result永远不会到达调用方。
因此:

return ref.child("hp").once("value", (snapshot) => {
  ...
})

接下来,您需要对ref.child("level").once("value", (snapshot) => {和其他单个once调用执行相同的操作。
最后,如果您有一个循环,其中您对循环中的每个项目执行异步作业(例如onceupdate),您可以使用Promise.all来等待所有这些作业完成,然后再完成作业并将值传回呼叫端。
我建议阅读MDN上Using Promises中的承诺,terminating functions: sync, async and promises上的Firebase文档,并观看那里链接的Doug的优秀视频系列。
不相关,但此代码比所需的复杂得多:

var ref = db.ref(`players/${user}/coins`);
ref.once("value", function(snapshot) {
    var coinsNow = parseInt(snapshot.val());
    const userRef = db.ref(`players/${user}`);
    userRef.update({
        'coins' : coinsNow+1
    })
});

Firebase实时数据库现在有一个内置的increment操作,这意味着您可以将其简化为:

db.ref(`players/${user}/coins`).set(firebase.database.ServerValue.increment(1));

相关问题