javascriptnode.jsasync-awaitcallstackrequest-promise

JavaScript - result undefined - forcing one method to complete before another?


I have the following NodeJS code running in an AWS Lambda:

const https = require('https');

exports.handler = async event => {
  try {
    
    const currentWeekNumber = getWeekNumber(new Date(Date.now()));
    
    const currentTournamentId = await getCurrentTournamentIdByWeekNumber(currentWeekNumber);
   
    // note: Issue is currentTournamentId is returned as undefined from above, so below method fails
    const leaderBoard = await getLeaderboardByTournId(currentTournamentId);
   
    return {
      statusCode: 200,
      headers: {'Content-Type': 'application/json'},
      body: JSON.stringify(leaderBoard),
    };
  } catch (error) {
    console.log('Error: ️', error);
    return {
      statusCode: 400,
      body: error.message,
    };
  }
};

function getCurrentTournamentIdByWeekNumber(currentWeekNumber) {
    
  const promise = new Promise((resolve, reject) => {
  
  const options = {
  host: 'MY_HOST',
  path: '/MY_PATH',
   headers: {
        'key': 'value'
      }
    };
  
    const req = https.get(options, res => {
      let rawData = '';

      res.on('data', chunk => {
        rawData += chunk;
      });

      res.on('end', () => {
        try {
          resolve(JSON.parse(rawData));
        } catch (err) {
          reject(new Error(err));
        }
      });
    });
    
    req.on('error', err => {
      reject(new Error(err));
    });
  });
  
  promise.then(result => {
    
   for (let i = 0; i <result.schedule.length; i++) {
     
    let weekNumber = result.schedule[i].date.weekNumber;
    
    if(currentWeekNumber == weekNumber) {
       return result.schedule[i].tournId;
      }
    }
   });
}
      
function getLeaderboardByTournId(tournId) {
    
  return new Promise((resolve, reject) => {
  
  const options = {
  host: 'MY_HOST',
  path: '/MY_PATH',
   headers: {
        'key': 'value'
      }
    };
  
    const req = https.get(options, res => {
      let rawData = '';

      res.on('data', chunk => {
        rawData += chunk;
      });

      res.on('end', () => {
        try {
          resolve(JSON.parse(rawData));
        } catch (err) {
          reject(new Error(err));
        }
      });
    });

    req.on('error', err => {
      reject(new Error(err));
    });
  });

}

function getWeekNumber(d) {
    // Copy date so don't modify original
    d = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()));
    // Set to nearest Thursday: current date + 4 - current day number
    // Make Sunday's day number 7
    d.setUTCDate(d.getUTCDate() + 4 - (d.getUTCDay()||7));
    // Get first day of year
    var yearStart = new Date(Date.UTC(d.getUTCFullYear(),0,1));
    // Calculate full weeks to nearest Thursday
    var weekNo = Math.ceil(( ( (d - yearStart) / 86400000) + 1)/7);
    // Return array of year and week number
    return weekNo;
}

I am having an issue where currentTournamentId is being passed into getLeaderboardByTournId as undefined, I think this is due to the execution order of my functions.

I know that the logic is correct in all the functions.

How can I ensure that getCurrentTournamentIdByWeekNumber completes and returns a result before getLeaderboardByTournId is called?

This is my first attempt at node lambda and only getting to grips with JS execution order!


Solution

  • You are correctly awaiting your getCurrentTournamentIdByWeekNumber method, however inside of that method, you're not returning anything so there's no promise to wait for.

    If you're add a return it will probably work:

    return promise.then(result => {
       ...