How do I return a promise from batch.commit() scheduled function in Firebase

870 Views Asked by At

This is my first time writing a scheduled function in Firebase. I'm trying to read sports data from a third party API and place that data into Firestore. I first built the function as a regular cloud function, verified that it writes to the database using batch, and then attempted to convert to a scheduled function that I want to run every 2 hours. Unfortunately, the data is not writing to Firestore and I am also getting the following error: Function returned undefined, expected Promise or value.

exports.getTodaysNCAABGames = functions.pubsub.schedule('every 2 hours').onRun((context) => {

  const options = {
    method: 'GET',
    url: 'https://sportspage-feeds.p.rapidapi.com/games',
    qs: {status: 'in progress', odds: 'any', league: 'NCAAB'},
    headers: {
      'x-rapidapi-key': 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
      'x-rapidapi-host': 'sportspage-feeds.p.rapidapi.com',
      useQueryString: true
    }
  };

  requesting(options, function (error, res, body) {
    if (error) throw new Error(error);
    const batch = db.batch();
    const bodyParsed = JSON.parse(body);
    const essentialResultsData = getNCAABEventData(bodyParsed.results);

    const ncaaRef = db.collection('ncaab');
    essentialResultsData.forEach(result => {
      batch.create(ncaaRef.doc(result.gameId), result);
    });
    return batch.commit();
  });
});

function getNCAABEventData(results) {
  const essentialEventData = [];
  results.forEach((result) => {
    const gameId = result.gameId.toString();
    const status = result.status;
    const oddsObject = result.odds;
    const scoreboard = result.scoreboard;
    const teams = result.teams;

    const resultData = {
      gameId: gameId,
      status: status,
      odds: oddsObject,
      scoreboard: scoreboard,
      teams: teams
    };

    essentialEventData.push(resultData);
  });
  return essentialEventData;
}

I guess that the batch.create returns a promise, but I thought with return batch.commit(), I would be returning all promises associated with each batch.create call.

I feel close but I'm just missing something very simple. Any and all help will be much appreciated!

1

There are 1 best solutions below

0
On BEST ANSWER

Your return batch.commit() does return a single promise, but it doesn't return a promise from the top level of the entire function. It's returning the promise from inside the callback function that you passed to requesting. That's not going to be propagated out of the top level function.

I suggest looking into an alternative for requesting that lets you work with promises instead of callbacks. A popular option is axios. Whatever you use, it should return a promise with the result of the query and let you chain the results in a form like this:

return request(...)
.then(result => {
    // work with the result to add data to Firestore
    return batch.commit()
})