Getting values from http request in nodejs

var latLon = "40.8,-77.8"; //Lat/lon
var cityCode = ""; //City code
var cityName = "";
var latLongCityCodeURL = ("http://dataservice.accuweather.com/locations/v1/cities/geoposition/search?apikey=" + weatherKey + "&q=" + latLon);

//Current Conditions Vars
var ccWeatherText = ""; //Text for weather at location
var ccTemp = 0; //Degrees Farenheit
var ccIcon = 0; //weather icon number https://developer.accuweather.com/weather-icons
var ccURL = "test"; //URL for get
//12 hour forecast Conditions Vars


//5 day forecast conditions Vars

//Get city code
http.get(latLongCityCodeURL, (resp) => {
    var that = this;
    resp.on("data", (chunk) => {
        var result = JSON.parse(chunk);
        var cityCode = result.Key;
        var cityName = result.EnglishName;
        console.log(cityCode + " " + cityName);
        that.cityName = cityName;
        that.cityCode = cityCode;
    });

}).on("error", (err) => {
    console.log("Error: " + err.message);
});


console.log(cityCode + " " + cityName);

So my issue is, I am making an http request using require('http'), what I want to do is parse the data and store it in my global variables so that I can use them for other requests. I have tried using var that=this and I have tried just assigning my global variables to the data. I am not sure how to do it, i just keep getting undefined. I know it has something to do with ASYNC and also something to do with the scope. Please help

6 answers

  • answered 2018-05-16 06:24 scetiner

    Your code block runs in a synchronized way and console.log part hits just after http.get call. The thing is http.get is an async function and its callback part will be called future ticks of NodeJS when your response has arrived.

  • answered 2018-05-16 06:27 Arif Khan

    You can use Promise to make http request, here is code that may help you

    const httpGet = url => {
        return new Promise((resolve, reject) => {
            http.get(url, res => {
                let body = '';
                res.on('data', chunk => body += chunk);
                res.on('end', () => {
                    try {
                        body = JSON.parse(body);
                    } catch (err) {
                        reject(new Error(err));
                    }
                    resolve({
                        cityCode: body.Key,
                        cityName: body.EnglishName
                    });
                });
            }).on('error', reject);
        });
    };
    
    
    httpGet(latLongCityCodeURL).then(data => {
        console.log(data.cityCode + " " + data.cityName);
    }).catch(err => console.log('Got error ', err));
    

  • answered 2018-05-16 06:28 cricket_007

    You must wait for the response, then send the other requests or log into. The scope isn't really the issue here, it's the order of operations that you're missing. You define a variable, then wait for a HTTP request, meanwhile you're immediately logging a value, then the request finishes (or times out or other error), and you can log again the value - at which point you see data.

    In other words, to fix the issue, other requests must be made from within a function of resp.on("end", which says when you've finished getting all data chunks

    And by "within", the code can still be in a separate method, outside those brackets, but you must call that particular function from within that response body.

    You should pass such asynchronous returned data through parameter variables, not update some external, global state in most cases

  • answered 2018-05-16 06:30 Terry Lennox

    You can save your result to a variable at various levels of scope.. just remember that most i/o calls in Node.js are asynchronous. Here's an example:

    var latLon = "40.8,-77.8"; //Lat/lon
    var cityCode = ""; //City code
    var cityName = "";
    var latLongCityCodeURL = ("http://dataservice.accuweather.com/locations/v1/cities/geoposition/search?apikey=" + weatherKey + "&q=" + latLon);
    
    //Current Conditions Vars
    var ccWeatherText = ""; //Text for weather at location
    var ccTemp = 0; //Degrees Farenheit
    var ccIcon = 0; //weather icon number https://developer.accuweather.com/weather-icons
    var ccURL = "test"; //URL for get
    
    
    var savedResult = null;
    
    //Get city code
    http.get(latLongCityCodeURL, (resp) => {
        var jsonData = '';
        resp.on("data", (chunk) => {
            jsonData += chunk;
        });
        resp.on("end", () => {
            savedResult = JSON.parse(jsonData);
        });
    }).on("error", (err) => {
        console.log("Error: " + err.message);
    });
    
    
    // Display saved result once available.
    setTimeout(displaySavedResult, 2000);
    
    function displaySavedResult() {
        if (!savedResult) {
            console.log('Last result is null!');
        } else {
            console.log('Last result: City Code: ' + savedResult.Key + " Name" + savedResult.EnglishName);
            console.log('Last result (all properties): ', JSON.stringify(savedResult, null, 2));
        }
    }
    

  • answered 2018-05-16 06:35 anshuVersatile

    var http = require('http');
    var latLon = "40.8,-77.8"; //Lat/lon
    var cityCode = ""; //City code
    var cityName = "";
    var latLongCityCodeURL = ("http://dataservice.accuweather.com/locations/v1/cities/geoposition/search?apikey=" + "fmKWSgaG5EAA0diCP2lSREEOYG6PC5q9" + "&q=" + latLon);
    var that;
    //Current Conditions Vars
    var ccWeatherText = ""; //Text for weather at location
    var ccTemp = 0; //Degrees Farenheit
    var ccIcon = 0; //weather icon number https://developer.accuweather.com/weather-icons
    var ccURL = "test"; //URL for get
    //12 hour forecast Conditions Vars
    
    
    //5 day forecast conditions Vars
    
    //Get city code
    getWeather = url => {
        return new Promise((resolve, reject) => {
            http.get(url, res => {
                let body = '';
                res.on('data', chunk => resolve(JSON.parse(chunk)));
            }).on('error', reject);
        });
    };
    
    
    getWeather(latLongCityCodeURL).then( weather => {
        console.log(weather.Key + " " + weather.EnglishName);
    })
    

  • answered 2018-05-16 06:35 owaishanif786

    var latLon = "40.8,-77.8"; 
    var latLongCityCodeURL = ("http://dataservice.accuweather.com/locations/v1/cities/geoposition/search?apikey=" + weatherKey + "&q=" + latLon);
    
    //Current Conditions Vars
    var ccWeatherText = ""; //Text for weather at location
    var ccTemp = 0; //Degrees Farenheit
    var ccIcon = 0; //weather icon number https://developer.accuweather.com/weather-icons
    var ccURL = "test"; //URL for get
    //12 hour forecast Conditions Vars
    
    
    //5 day forecast conditions Vars
    
    
    //Get city code
    function getCityCode(latLongCityCodeURL){
     return new Promise((resolve, reject) => {
      http.get(latLongCityCodeURL, (resp) => {
        resp.on("data", (chunk) => {
            var result = JSON.parse(chunk);
            var cityCode = result.Key;
            var cityName = result.EnglishName;
            resolve({cityCode, cityName});
        });
    
        }).on("error", (err) => {
           reject(err);
          console.log("Error: " + err.message);
       });
    
     })
    }
    
    
    getCityCode(latLongCityCodeURL)
    .then((result) => { 
     console.log(result.cityCode, result.cityName) 
    }).catch((err) => console.log(err))
    

    Another way is to use async-await API interface which is supported in node 8.

    async function getCityCode(latLongCityCodeURL){
     const result = await http.get(latLongCityCodeURL, (resp) => {
            resp.on("data", (chunk) => {
                var result = JSON.parse(chunk);
                var cityCode = result.Key;
                var cityName = result.EnglishName;
                return {cityCode, cityName};
            });
    
            }).on("error", (err) => {
               return err;
              console.log("Error: " + err.message);
           });
    
      return result;
    }
    
    getCityCode(latLongCityCodeURL)
    .then((res) => { 
    
    console.log(res.cityCode, res.cityName)
    
    })