How to access variables within closures in Javascript

522 views Asked by At

I am creating a weather app using Node.js to access the current weather.

When I call the openweatherapp API, the temperature variable retrieved through the JSON that I am trying to pass on to module.exports is nested within a series of closure functions.

Is there any way for me to access the temperature and pass it through module.exports so I can retrieve the data from another file?

var http = require('http')

const apiKey = "myAPIkey"

// Connect to API URL api.openweathermap.org/data/2.5/weather?q={city name}
function accessWeather(city, callback) {

  var options = {
    host: "api.openweathermap.org",
    path: "/data/2.5/weather?q=" + city + "&appid=" + apiKey + "",
    method: "GET"
  }

  var body = ""

  var request = http.request(options, function(response) {

    response.on('data', function(chunk) {
      body += chunk.toString('utf8')
    })
    response.on('end', function() {

      var json = JSON.parse(body)
      var temperature = parseInt(json["main"]["temp"] - 273)
    })
  })
  request.end()
}

temp = accessWeather("Calgary")
console.log(temp)

module.exports = {
  accessWeather: accessWeather
}
1

There are 1 answers

0
Rosmarine Popcorn On

Well here we have a misconception of how async works in JavaScript. You can't return data that are going to be loaded in the future.

There are few options to solve this.

1 ) Export a function that takes another function as a parameter and call that function when you resolve your data :

module.export = function accessWeather(city, callback) {

  var options = {
    host: "api.openweathermap.org",
    path: "/data/2.5/weather?q=" + city + "&appid=" + apiKey + "",
    method: "GET"
  }

  var body = ""

  var request = http.request(options, function(response) {

    response.on('data', function(chunk) {
      body += chunk.toString('utf8')
    })
    response.on('end', function() {

      var json = JSON.parse(body)
      var temperature = parseInt(json["main"]["temp"] - 273);
      callback(temperature);
    })
  })
  request.end()
}

2 ) Because the callback style is legacy now, you can do something even better with Promises.

module.export = function accessWeather(city, callback) {

  return new Promise(function(resolve, reject){
     var options = {
    host: "api.openweathermap.org",
    path: "/data/2.5/weather?q=" + city + "&appid=" + apiKey + "",
    method: "GET"
  }

  var body = ""

  var request = http.request(options, function(response) {

    response.on('data', function(chunk) {
      body += chunk.toString('utf8')
    })
    response.on('end', function() {

      var json = JSON.parse(body)
      var temperature = parseInt(json["main"]["temp"] - 273);
      resolve(temperature);
    })
  })
  request.end()
  });
}

You can use also ESNext features like Generators and what I prefer even more if using Observables.