Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

135
Views
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 answers
Answer question

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 Report

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!