gpt4 book ai didi

javascript - 为什么这个 Firebase 可调用函数不返回值?

转载 作者:行者123 更新时间:2023-11-29 20:53:35 26 4
gpt4 key购买 nike

我有一个应该返回值的可调用函数,但唯一返回的是空值。以下是该功能的当前版本。我也尝试过返回第一个 promise (最初的 once 调用),最后在另一个 then 中返回 GUID。在那种情况下它实际上返回了数据,但它立即返回并且 GUID 为空。

我怎样才能实现我的目标并仍然返回 GUID?如果我将使用我生成的新 GUID 或数据库中已存在的 GUID,我不知道何时调用该函数。

这里有一个类似的问题:Receiving returned data from firebase callable functions ,但在那种情况下,这是因为他从未从函数中返回一个 promise 。我在所有代码路径上返回一个 promise 。 除非我必须从 once 调用中返回初始 promise ?在这种情况下,我如何在我还不知道 GUID 时返回它?

我还试图在几个地方抛出错误,错误显示在函数的日志中,但从未发送到调用该函数的客户端。

我将结束此处的示例:https://firebase.google.com/docs/functions/callable

抱歉代码炸弹。

调用函数:

var newGame = firebase.functions().httpsCallable('findCreateGame');
newGame({}).then(function(result) {
// Read result of the Cloud Function.
//var sGameID = result.data.guid;
console.log(result);
}).catch(function(error) {
console.log(error);
});

功能:

exports.findCreateGame = functions.https.onCall((data, context) => {
console.log("findCurrentGame Called.")
/**
* WHAT NEEDS DONE
*
*
* Pull in user's information
* Determine their win/loss ratio and search for a game using transactions in either low medium or high queue
* If there are no open games in their bracket, search the one above, then below
* If no open games anywhere, create a new game in their bracket
* If an open game is found, write the UID to the game and add the game's ID to the user's profile
*
*/

var uid = context.auth.uid;
var section = "";
var sUsername = "";
var sProfilePic = "";
var currentGames = null;
var sGUID = "";

//Get the user's info
var userref = admin.database().ref('users/' + uid);
userref.once("value", function(data) {
var ratio = 0;
var wins = parseInt(data.val().wins);
var losses = parseInt(data.val().losses);
var lives = parseInt(data.val().lives);

if (lives < 1){
//This user is out of lives, should not have been able to get here
//Throw an exception so that we can see why it failed
throw new functions.https.HttpsError('permission-denied', 'You do not have enough lives to start a new game.');
}
sUsername = data.val().username;
sProfilePic = data.val().profilepicture;

//Handle if they have no losses
if (losses == 0){
ratio = 100;
} else {
ratio = (wins / losses) * 100;
}

//If they have played less than 5 games, put them in noob tier
if (wins + losses < 5){
ratio = 0;
}

if (ratio <= 33){
section = "noob";
} else if (ratio > 33 && ratio <= 66){
section = "average";
} else {
section = "expert";
}
}).then(() => {
//Get all of the games this user is currently in
admin.database().ref('games').orderByChild(uid).once('value', function(data) {
currentGames = data.val();
}).then(() => {

//Generate a new GUID in case we need to set up a new game
sGUID = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});



var queueref = admin.database().ref('gamequeue/' + section);
queueref.transaction(function(currentGUID) {

if (currentGUID == null){
//Write our GUID in the queue
return sGUID;
} else {
//Get the id of the game we just got
sGUID = currentGUID

return null;
}
}).then((res) => {

if (res.snapshot.val() != null){
//This means we are creating the game lobby

//Generate a new answer
var newAnswer = "";
while (newAnswer.length < 4){
var temp = Math.floor(Math.random() * 9) + 1;

temp = temp.toString();

if (!newAnswer.includes(temp)){
newAnswer += temp;
}
}

var obj = {username: sUsername, score: 0, profilepicture: sProfilePic};

return admin.database().ref('games/' + sGUID).set({id: sGUID, requestor: uid, [uid]: obj, answer: newAnswer, turn: uid, status: 'pending'}).then(() => {
return {guid: sGUID};
});
} else {
//We found a game to join

//If we are in a duplicate request situation, make sure the GUID is a string
if (typeof(sGUID) != 'string'){
sGUID = Object.keys(sGUID)[0];
}

//Make sure we didn't find our own game request
if (currentGames[sGUID] != null){
//Add this GUID back to the queue, we shouldn't have removed it
return admin.database().ref('gamequeue/' + section + '/' + sGUID).set('');

//Throw an exception that says you can only have one open game at a time
throw new functions.https.HttpsError('already-exists', 'We are still finding a match for your last request. You are only allowed one open request at a time.');

} else {
//Get the current game info
admin.database().ref('games/' + sGUID).once('value', function(data) {
var sRequestor = data.val().requestor;
var sOpponentUsername = data.val()[sRequestor].username;
var sOpponentProfilePic = data.val()[sRequestor].profilepicture;

//Write all of our info to the game
return admin.database().ref('games/' + sGUID).update({[sRequestor]: {opponentusername: sUsername, opponentprofilepicture: sProfilePic}, [uid]: {username: sUsername, score: 0, opponentusername: sOpponentUsername, opponentprofilepicture: sOpponentProfilePic}, status: 'active'}).then(() => {
return {guid: sGUID};
});
});
}
}
});
});
})
});

最佳答案

documentation for callable functions解释:

To return data after an asynchronous operation, return a promise. The data returned by the promise is sent back to the client.

您有许多必须链接在一起的异步操作。需要将 return 添加到这些语句中的每一个(如图所示):

return userref.once("value", function(data) {...

return admin.database().ref('games').orderByChild(uid).once('value', function(data) {...

return queueref.transaction(function(currentGUID) {...

return admin.database().ref('games/' + sGUID).once('value', function(data) {...

关于javascript - 为什么这个 Firebase 可调用函数不返回值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50499413/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com