Почему эта вызываемая Firebase функция не возвращает значение? - PullRequest
0 голосов
/ 24 мая 2018

У меня есть вызываемая функция, которая должна возвращать значение, но единственное, что когда-либо возвращалось, это ноль.Ниже приведена текущая версия функции.Я также попытался получить возврат по первому обещанию (исходному вызову once) и в конце по другому then, возвращающему GUID.В этом случае он фактически возвращал данные, но сразу возвращал, и GUID был пуст.

Как я могу достичь своей цели и при этом вернуть GUID?Я не знаю, когда вызывается функция, если я буду использовать новый GUID, который я генерирую, или тот, который уже существует в базе данных.

Здесь есть аналогичный вопрос: Получение возвращенных данных отвызываемые firebase функции , но в этом случае это произошло потому, что он никогда не возвращал обещание функции.Я возвращаю обещание на всех путях кода. Если я не должен вернуть первоначальное обещание из once вызова? В каком случае, как я могу вернуть 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};
                            });
                        });
                    }
                }
            });
        });
    })
});

1 Ответ

0 голосов
/ 24 мая 2018

Документация для вызываемых функций объясняет:

Чтобы вернуть данные после асинхронной операции, верните обещание.Данные, возвращаемые обещанием, отправляются обратно клиенту.

У вас есть много асинхронных операций, которые должны быть объединены в цепочку.* 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) {...
...