我有这样的代码
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循环计算玩家对怪物的生命和伤害。这可以正常工作。问题是当我想发送结果变量的数据给用户进行进一步的工作。它每次都返回null。你知道错误在哪里吗?我唯一能想到的是错误会出现在返回中。也许它在请求的数据有任何值之前被调用。我不知道。我想不明白。
但是我确信我想要发送给用户的值不是空的,而是有他们应该有的值。下面是来自firebase控制台
的日志Firebase控制台日志
这是我用于客户端返回的代码。这里总是得到null
var battle = firebase.functions().httpsCallable('battle')
battle().then(result => {
console.log(result)
})
更新:弗兰克的回答很有方向性。但我不认为这是完全清楚的。经过长时间的搜索,我在这里找到了一个更容易理解的解决方案:https://medium.com/@stephane.giron/firebasecloudfunctions-oncall-return - before-endoffunction-2d898d8ff259
我只是在代码的开头改变了这一点,并将其添加到末尾
exports.battle = functions.https.onCall((data, context) => {
if(context.auth){
return new Promise(function(resolve, reject) {
/*
. . . .
code
. . . .
*/
reslove(result)
)}
我希望这对其他人有所帮助。我建议将.catch
添加到代码的末尾,以防止可能的错误,但我不完全确定,所以我不想混淆
promise的结果冒泡到调用者,但只有当您实际上从then
或catch
回调中返回它们时。因此,在每个once
回调中,您需要确保将return
的值传递给调用者。
所以首先,你在顶层云函数中丢失了顶层return
语句,这意味着你的return result
永远不会到达调用者。
:
return ref.child("hp").once("value", (snapshot) => {
...
})
接下来,您需要对ref.child("level").once("value", (snapshot) => {
和其他单独的once
调用执行相同的操作。
最后,如果您有一个循环,其中您对循环中的每个项目执行异步操作(例如once
或update
),您可以使用Promise.all
等待所有这些操作完成,然后完成操作并返回一个值给调用者。
我建议你在MDN上使用Promises中阅读Promises,在Firebase文档中关于终止函数:sync, async和Promises,并观看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));