Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

JavaScript

Neil Ganotisi
Neil Ganotisi
20,975 Points

Primary function proceeds while a vital component is still being generated. How do I make the function wait?

Hey guys, working on a project on Node that kind of uses the beginning code base from the Express Basics course.

I stumbled upon a problem when I a POST request gets made at a certain route.

Desired result: Server makes a request to an Overwatch API endpoint, and returns the response from the API to the route /lookup.

Actual result: Server makes a request to an Overwatch API endpoint, Node proceeds to finish the called function without completing the request, leaving the response 'undefined'.

Here's the app.js file I have, and the console result to go with it.

//Load npm modules
const express = require('express');
const bodyParser = require('body-parser');
const request = require('request');

//Set obj 'app' to express();
const app = express();

app.use(bodyParser.urlencoded({ extended: false}));

app.set('view engine', 'pug');

app.get('/', (req, res, next) => {
    res.render('index');
});

app.post('/lookup', (req, res, next) => {
    const battletag = req.body.battletag;
    console.log("running");
    var stats = lookupStats(battletag);
    console.log("lookupStats() completed. Attempting to render stats.");
    res.render(stats);
});

app.listen(3000, () => {
    console.log('The application is running on localhost:3000!')
});


function apiRequestObj(battletag) {
    var requestObj = {
        uri: "https://owapi.net/api/v3/u/" + battletag + "/blob?platform=pc",
        timeout: 10000,
        headers: {
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.43 Safari/537.31'
        }
    }
    return requestObj;
}

function apiRequest(requestObj) {
    request(requestObj, function(err, res, body) {
        if (err) {
            return "Error: " + err;
        } else {
            var result = JSON.parse(body);
            result = result.us.stats.competitive.overall_stats;
            console.log(result);
            return result;
        }
    });
}

function lookupStats(battletag) {
    battletag = battletag.replace('#', '-');
    console.log("Searching Battletag: " + battletag);
    var requestObj = apiRequestObj(battletag);
    var apiResult = apiRequest(requestObj);
    console.log(apiResult);
    return apiResult;
}
The application is running on localhost:3000!
running
Searching Battletag: Unreal-11505
undefined
lookupStats() completed. Attempting to render stats.
TypeError: Path must be a string. Received undefined
    at assertPath (path.js:7:11)
    at extname (path.js:1431:5)
    at new View (/Users/neil/Dropbox/Programming/Web Development/owapi/node_modules/express/lib/view.js:56:14)
    at EventEmitter.render (/Users/neil/Dropbox/Programming/Web Development/owapi/node_modules/express/lib/application.js:570:12)
    at ServerResponse.render (/Users/neil/Dropbox/Programming/Web Development/owapi/node_modules/express/lib/response.js:1008:7)
    at app.post (/Users/neil/Dropbox/Programming/Web Development/owapi/app.js:22:9)
    at Layer.handle [as handle_request] (/Users/neil/Dropbox/Programming/Web Development/owapi/node_modules/express/lib/router/layer.js:95:5)
    at next (/Users/neil/Dropbox/Programming/Web Development/owapi/node_modules/express/lib/router/route.js:137:13)
    at Route.dispatch (/Users/neil/Dropbox/Programming/Web Development/owapi/node_modules/express/lib/router/route.js:112:3)
    at Layer.handle [as handle_request] (/Users/neil/Dropbox/Programming/Web Development/owapi/node_modules/express/lib/router/layer.js:95:5)
{ level: 61,
  comprank: 2031,
  games: 116,
  win_rate: 53.21,
  losses: 51,
  rank_image: 'https://d1u1mce87gyfbn.cloudfront.net/game/playerlevelrewards/0x0250000000000928_Border.png',
  wins: 58,
  ties: 7,
  prestige: 1,
  avatar: 'https://d1u1mce87gyfbn.cloudfront.net/game/unlocks/0x02500000000002F7.png',
  tier: 'gold' }

Does anyone have an idea of how I can make Node wait for the response from the API endpoint before proceeding?