Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

136
Vistas
Realtime database cloud function sends result back before finishing

I'm trying to perform some realtime database tasks, which after completion, should send back a result back to the client so the client knows when the tasks have finished.

exports.createGame = functions.https.onCall((data, context) => {
    const gameChosen = data.gameChosen; 
    const adminName = data.adminName;
    const numberOfRounds = data.numberOfRounds;
    let gameID = Math.floor(100000 + Math.random() * 900000).toString();
    var numberOfQuestions = 0;
    var questionsPicked = [];

    getGameQuestions(gameChosen, numberOfRounds).then((questionsPickedArray) => {
        db.ref(`live-games/${gameChosen}/${gameID}`).set(
         {
           playerAdmin: adminName,
           game: gameChosen,
           players: [adminName],
           questions: questionsPickedArray,
           datetimeCreated: Date.now(),
         },
          (error) => {
            if (error) {
              console.log("Data could not be saved." + error);
            } else {
              console.log("Data saved successfully.");
              return {
                gameChosen: gameChosen,
                gameAdmin: adminName,
                questions: questionsPicked,
                gameID: gameID,
              };
             }
           } 
        );
      });
    });

function getGameQuestions(gameChosen, numberOfRounds) {
  var questionsPicked = [];
  var numberOfQuestions = 0;
  return new Promise(function (resolve, reject) {
    db.ref(`games/${gameChosen}`).once("value", function (snapshot) {
      val = snapshot.val();
      numberOfQuestions = val.questionsAvailable;
      for (var i = 0; i < numberOfRounds; i++) {
        let questionNumber = Math.floor(Math.random() * (numberOfQuestions - 0 + 1) + 0);
        if (!questionsPicked.includes(questionNumber)) {
          questionsPicked.push(questionNumber);
        }
      }
      resolve(questionsPicked);
    });
  });
}

I've tried to create a promise due to the fact some realtime database tasks do not return a promise - wasn't sure which one. Based on the logs, the function completed with a status code of 200 and then a couple seconds after, the realtime database gets updated with the values. The database should be updated, the result sent back to the client and then the function should finish. It's currently sending back NULL to the client - presuming the function is sending it back as soon as it runs.

How does one perform realtime database tasks one after another efficiently?

about 4 years ago · Juan Pablo Isaza
2 Respuestas
Responde la pregunta

0

You have to return that Promise as mentioned here.

To return data after an asynchronous operation, return a promise.

exports.createGame = functions.https.onCall((data, context) => {
    const gameChosen = data.gameChosen; 
    const adminName = data.adminName;
    const numberOfRounds = data.numberOfRounds;
    let gameID = Math.floor(100000 + Math.random() * 900000).toString();
    var numberOfQuestions = 0;
    var questionsPicked = [];

    getGameQuestions(gameChosen, numberOfRounds).then((questionsPickedArray) => {
        //Just add a return here
        return db.ref(`live-games/${gameChosen}/${gameID}`).set( 
         {
           playerAdmin: adminName,
           game: gameChosen,
           players: [adminName],
           questions: questionsPickedArray,
           datetimeCreated: Date.now(),
         })
         .catch((error) => {
            if (error) {
              console.log("Data could not be saved." + error);
            } else {
              console.log("Data saved successfully.");
              return {
                gameChosen: gameChosen,
                gameAdmin: adminName,
                questions: questionsPicked,
                gameID: gameID,
              };
            }
          }) 
        );
      });
    });
about 4 years ago · Juan Pablo Isaza Denunciar

0

The following modifications should do the trick:

exports.createGame = functions.https.onCall((data, context) => {
    const gameChosen = data.gameChosen;
    const adminName = data.adminName;
    const numberOfRounds = data.numberOfRounds;
    let gameID = Math.floor(100000 + Math.random() * 900000).toString();
    var numberOfQuestions = 0;
    var questionsPicked = [];
 
    return getGameQuestions(gameChosen, numberOfRounds)  // We return the Promises chain, see below for more details
        .then((questionsPickedArray) => {
            return db.ref(`live-games/${gameChosen}/${gameID}`).set(
                {
                    playerAdmin: adminName,
                    game: gameChosen,
                    players: [adminName],
                    questions: questionsPickedArray,
                    datetimeCreated: Date.now(),
                })
        })
        .then(() => {
            return {
                gameChosen: gameChosen,
                gameAdmin: adminName,
                questions: questionsPicked,
                gameID: gameID,
            };
        })
        .catch((error) => {
            // See https://firebase.google.com/docs/functions/callable#handle_errors
            throw new functions.https.HttpsError(...);
        });
});

function getGameQuestions(gameChosen, numberOfRounds) {
    var questionsPicked = [];
    var numberOfQuestions = 0;
        return db.ref(`games/${gameChosen}`).once("value")  // Here too, we return the Promises chain
        .then(snapshot => {
            val = snapshot.val();
            numberOfQuestions = val.questionsAvailable;
            for (var i = 0; i < numberOfRounds; i++) {
                let questionNumber = Math.floor(Math.random() * (numberOfQuestions - 0 + 1) + 0);
                if (!questionsPicked.includes(questionNumber)) {
                    questionsPicked.push(questionNumber);
                }
            }
            return questionsPicked;
        });
}

So, you need to chain the Promises and return the result to the client as shown above: as explained in the doc "the data returned by the promise is sent back to the client" (which is the case if we return the Promises chain) and the data shall be an object/value that can be JSON encoded (which is the case with the { gameChosen: gameChosen, gameAdmin: adminName, ...} object).

For the getGameQuestions() function, since the once() method returns a Promise, you don't need to encapsulate it into a Promise. Again, just return the promises chain composed by once().then(...).

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda