# Show local weather API

**URL:** <https://forum.freecodecamp.org/t/show-local-weather-api/53140>\
**Category:** I Built This\
**Created:** [November 8, 2016, 7:11am UTC](https://forum.freecodecamp.org/t/show-local-weather-api/53140 "2016-11-08T07:11:12Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![rmonastra](https://sea3.discourse-cdn.com/freecodecamp/user_avatar/forum.freecodecamp.org/rmonastra/32/67696_2.png) [@rmonastra](https://forum.freecodecamp.org/u/rmonastra)\
**Post date:** [November 8, 2016, 7:11am UTC](https://forum.freecodecamp.org/t/show-local-weather-api/53140/1 "2016-11-08T07:11:12Z")

</div>

Hello,  
I’m working on the Show Weather Challenge. [Ip-api.com](http://Ip-api.com) is down, so I’m trying to get JSON data by zip code. My .getJSON isn’t returning the city name. I’m having trouble getting the city name into #city. Any help would be appreciated.

```
function getZip() {

 var zip = document.getElementById("zipcode").value;

 var api = 'api.openweathermap.org/data/2.5/weather?zip=' + zip + ',us' + '&appid=1800147fe71b1f960c693e7f65ee030a';

console.log(api); //tests api url is correct
   var city;
  $.getJSON(api,function(data){

 var city = data.name;
  })

}

$("#city").html(city);
```

---

<div class="post-metadata">

**Author:** ![michealhall](https://avatars.discourse-cdn.com/v4/letter/m/59ef9b/32.png) [@michealhall](https://forum.freecodecamp.org/u/michealhall)\
**Post date:** [November 8, 2016, 7:31am UTC](https://forum.freecodecamp.org/t/show-local-weather-api/53140/2 "2016-11-08T07:31:42Z")

</div>

Your

```auto
$("#city").html(city);
```

is in the wrong place (should be inside the getJSON callback).

Outside of the callback, the city variable you create is undefined.

Remember, getJSON is asynchronous, so the line where you attempt to insert city into the interface will execute prior to getJSON returning any data. It will only see that data from inside the callback.

---

<div class="post-metadata">

**Author:** ![rmonastra](https://sea3.discourse-cdn.com/freecodecamp/user_avatar/forum.freecodecamp.org/rmonastra/32/67696_2.png) [@rmonastra](https://forum.freecodecamp.org/u/rmonastra)\
**Post date:** [November 8, 2016, 2:53pm UTC](https://forum.freecodecamp.org/t/show-local-weather-api/53140/3 "2016-11-08T14:53:26Z")

</div>

Is this what you’re talking about?

```
function getZip() {

var zip = document.getElementById("zipcode").value;

var api = 'api.openweathermap.org/data/2.5/weather?zip=' + zip + ',us' + '&appid=1800147fe71b1f960c693e7f65ee030a';

console.log(api);
var city;
$.getJSON(api,function(data){ 

var city = data.name;
$("#city").html(city);
 })

}
```

---

<div class="post-metadata">

**Author:** ![technbuzz](https://sea3.discourse-cdn.com/freecodecamp/user_avatar/forum.freecodecamp.org/technbuzz/32/164462_2.png) [@technbuzz](https://forum.freecodecamp.org/u/technbuzz)\
**Post date:** [November 8, 2016, 3:25pm UTC](https://forum.freecodecamp.org/t/show-local-weather-api/53140/4 "2016-11-08T15:25:23Z")

</div>

This will return **Reference Error** because browser won’t be able to find **city** in the global name space, neither it’s deceleration nor it’s instantiation.

---

<div class="post-metadata">

**Author:** ![rmonastra](https://sea3.discourse-cdn.com/freecodecamp/user_avatar/forum.freecodecamp.org/rmonastra/32/67696_2.png) [@rmonastra](https://forum.freecodecamp.org/u/rmonastra)\
**Post date:** [November 8, 2016, 5:07pm UTC](https://forum.freecodecamp.org/t/show-local-weather-api/53140/5 "2016-11-08T17:07:02Z")

</div>

First, thank you for your assistance. I’m trying several things and honestly, I’m stuck.

```
$('#city').html();

function getZip(){

 var zip = document.getElementById("zipcode").value;
var api = 'api.openweathermap.org/data/2.5/weather?zip=' + zip + ',us' + '&appid=1800147fe71b1f960c693e7f65ee030a';

console.log(api);  

$.getJSON(api,function(data){
  var city = data.name;  
});

  $('#city').html(city);
}
```

---

<div class="post-metadata">

**Author:** ![technbuzz](https://sea3.discourse-cdn.com/freecodecamp/user_avatar/forum.freecodecamp.org/technbuzz/32/164462_2.png) [@technbuzz](https://forum.freecodecamp.org/u/technbuzz)\
**Post date:** [November 8, 2016, 5:18pm UTC](https://forum.freecodecamp.org/t/show-local-weather-api/53140/6 "2016-11-08T17:18:25Z")

</div>

What issues are you getting? I can test it here as I’m getting problem with the token

---

<div class="post-metadata">

**Author:** ![rmonastra](https://sea3.discourse-cdn.com/freecodecamp/user_avatar/forum.freecodecamp.org/rmonastra/32/67696_2.png) [@rmonastra](https://forum.freecodecamp.org/u/rmonastra)\
**Post date:** [November 8, 2016, 5:38pm UTC](https://forum.freecodecamp.org/t/show-local-weather-api/53140/7 "2016-11-08T17:38:22Z")

</div>

My function seems to not be getting the city information from the JSON data that I’m trying to access. A user puts in their zip code. The user input is being passed into the API call but I’m having trouble accessing the JSON data. I would like to be able to print information to console first, then figure out passing it to html.

---

<div class="post-metadata">

**Author:** ![michealhall](https://avatars.discourse-cdn.com/v4/letter/m/59ef9b/32.png) [@michealhall](https://forum.freecodecamp.org/u/michealhall)\
**Post date:** [November 8, 2016, 7:28pm UTC](https://forum.freecodecamp.org/t/show-local-weather-api/53140/8 "2016-11-08T19:28:54Z")

</div>

Hi @rmonastra,

No, you need to move the entire

```auto

$('#city').html(city);

```

into

```auto

$.getJSON(api,function(data){
  var city = data.name;  
});

```

That function being passed to $.getSJON is a callback - it is _called back_ when the getJSON ajax call completes. The getJSON function calls back your callback function and passes in the data argument.

That’s the only place the data value will be accessible for use, no where else can see it.

So, assuming your API call is returning successfully, you need:

```auto

$.getJSON(api,function(data){

  var city = data.name; 
  $('#city').html(city);

  // YOU COULD ALSO console.log( data ); HERE TO INSPECT THE RESULTS

});

```

P.S. - Normal function scoping rules would allow you to declare your city variable outside getJSON and then access it later, like you had it before, but because getJSON is asynchronous, and Javascript keeps executing while waiting for a result, your statements after getJSON are executed before city has any value. That technique does not work with asynchronous calls. You could see that by doing something like:

```auto

console.log( 'First!' );

$.getJSON(api,function(data){
  
  console.log( 'Second!' );

});

console.log( 'Third!' );

```

And looking at the order in which they are logged to the console.

Hope that helps!  
~Micheal

---

<div class="post-metadata">

**Author:** ![spoonhonda](https://sea3.discourse-cdn.com/freecodecamp/user_avatar/forum.freecodecamp.org/spoonhonda/32/29794_2.png) [@spoonhonda](https://forum.freecodecamp.org/u/spoonhonda)\
**Post date:** [January 24, 2017, 6:56am UTC](https://forum.freecodecamp.org/t/show-local-weather-api/53140/9 "2017-01-24T06:56:06Z")

</div>

I just finished my Weather API project. What @michealhall michealhall said is mostly true, however there actually is a way to create a global object variable extracted from the $.getJSON API call. It took me three days to figure it out. haha I played around with your code to so you (and others) can see that it IS possible to work with a global object outside of $.getJSON I used your code and changed it to demonstrate what I’m talking about.

```
$(document).ready(function() {
	var JsonObjectAPI = {}; //Global object variable that the API will load into
	var city = "No City Name Yet"; //Global string variable for city name
	
	function getZip() {
		//var zip = document.getElementById("zipcode").value;
		var zip = 90210;
		
		var api = 'http://api.openweathermap.org/data/2.5/weather?zip=' + zip + ',us' + '&appid=1800147fe71b1f960c693e7f65ee030a';
		//console.log(api); //tests api url is correct
		
		//Must include the 'async':false parameter or the object data won't get captured when loading
		JsonObjectAPI = JSON.parse($.ajax({'url': api, 'async': false}).responseText);
		
		city = JsonObjectAPI.name;
		//console.log(city);
	}
	
	setTimeout(getZip()); //runs the getzip function for testing
	
	console.log(JsonObjectAPI);
	console.log(city);
	
	$("#city").html(city);
});
```

---

<div class="post-metadata">

**Author:** ![michealhall](https://avatars.discourse-cdn.com/v4/letter/m/59ef9b/32.png) [@michealhall](https://forum.freecodecamp.org/u/michealhall)\
**Post date:** [January 24, 2017, 6:10pm UTC](https://forum.freecodecamp.org/t/show-local-weather-api/53140/10 "2017-01-24T18:10:52Z")

</div>

If you set async to false, you are negating the entire point to **ansynchronous** requests which allow other processing to continue while you wait for your request to return. So, you really don’t want to do that. This is going to cause page freezing and un-responsive UI.

> **[Synchronous and asynchronous requests](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Synchronous_and_Asynchronous_Requests)**
>
> XMLHttpRequest supports both synchronous and asynchronous communications. In general, however, asynchronous requests should be preferred to synchronous requests for performance reasons.

That is why you are able to, lower in the code, log the values from `JsonObjectAPI` and `city`.

There are other ways to pass around information to be used outside of callbacks - global variables and `async: false` I would not recommend.

Regards,  
Micheal

---

<div class="post-metadata">

**Author:** ![spoonhonda](https://sea3.discourse-cdn.com/freecodecamp/user_avatar/forum.freecodecamp.org/spoonhonda/32/29794_2.png) [@spoonhonda](https://forum.freecodecamp.org/u/spoonhonda)\
**Post date:** [January 24, 2017, 7:01pm UTC](https://forum.freecodecamp.org/t/show-local-weather-api/53140/11 "2017-01-24T19:01:11Z")

</div>

> [@michealhall](#):
>
> There are other ways to pass around information to be used outside of callbacks

I understand your points. Can you please explain to us what the other options we have of passing around information outside of callbacks?

---

<div class="post-metadata">

**Author:** ![michealhall](https://avatars.discourse-cdn.com/v4/letter/m/59ef9b/32.png) [@michealhall](https://forum.freecodecamp.org/u/michealhall)\
**Post date:** [January 24, 2017, 8:16pm UTC](https://forum.freecodecamp.org/t/show-local-weather-api/53140/12 "2017-01-24T20:16:51Z")

</div>

Here is a simple method/function from a project I work on.

`loadCollection` is an asynchronous method which loads data from the server. Various methods may call it (some directly, others by triggering an event). The method itself does nothing other than load the data requested (this is specified by the provided collectionID).

The method may not actually need to load the data - if it finds it already loaded and it hasn’t been told to `force_reload`, it returns the data it has, saving a round trip to the server.

The data requested is JSON format, but not **_exactly_** the format we want (there are some links/relationships we’d like to establish and this collection may need to replace one already in memory). So, when the data is returned, the callback to the ajax request executes an update function, which does that data updating/replacement as needed.

At that point, the data is ready to use and function calls any callback provided, passing in the newly returned data. Additionally, it resolves the `Promise` which was created and returned, also passing in the data.

This way, the function can be called directly using the `.then()` syntax to process the results of the call after it is complete, or - when called via say an event triggering - the event can pass in a callback, which is executed.

Multiple collections can be loaded at once and all of this data is all maintained in a list (an Array) which is modified via methods like `COLLECTIONS.update.collectionReference()` and accessed via methods like the `COLLECTIONS.get.collectionReference()`

Written this way, the load function doesn’t care **_why_** you are loading data, it simply loads the data you requested and then executes any callback/resolves a promise. All of the handling of the data returned is done external to the load call and passed back out.

I’m not suggesting this method is perfect (I found a bug while I was writing this up!) But it’s a common pattern for me when handling data loaded from the server.

Anyway, hope this helps out a bit!

```auto

function loadCollection( collectionID, include_imagestores, force_reload, callback ) => {

	return new Promise( ( resolve ) => {

		const collection = COLLECTIONS.get.collectionReference( collectionID );
		
		if ( collection && ( include_imagestores && collection.imageStores && collection.imageStores.length ) && !force_reload )
		{
			completeLoad( collection, resolve, callback );
			return;
		}
		
		COLLECTIONS.load.dataFromServer( 'collection', 
			{
				'collectionID' : collectionID, 
				'includeImageStores' : ( include_imagestores ) ? 1 : 0, 
				'forceReload' : ( force_reload ) ? 1 : 0 
			}) 
			.then( ( data ) => {
				
				COLLECTIONS.update.collectionList( data );
				completeLoad( COLLECTIONS.get.collectionReference( collectionID ), resolve, callback );

			});
		
	});

	function completeLoad( collection, resolve, callback ){
		
		( typeof callback === 'function' ) &&
			callback( collection );
			
		resolve( collection );
		
	}

}

```

---

<div class="post-metadata">

**Author:** ![spoonhonda](https://sea3.discourse-cdn.com/freecodecamp/user_avatar/forum.freecodecamp.org/spoonhonda/32/29794_2.png) [@spoonhonda](https://forum.freecodecamp.org/u/spoonhonda)\
**Post date:** [January 25, 2017, 5:29pm UTC](https://forum.freecodecamp.org/t/show-local-weather-api/53140/13 "2017-01-25T17:29:53Z")

</div>

Wow, that seems like a lot of code just to capture an json object! It will take me some time to digest how it works. But it seems like we should have a **short and simple way** to capture json data globally and asynchronously.

---

<div class="post-metadata">

**Author:** ![michealhall](https://avatars.discourse-cdn.com/v4/letter/m/59ef9b/32.png) [@michealhall](https://forum.freecodecamp.org/u/michealhall)\
**Post date:** [January 25, 2017, 6:31pm UTC](https://forum.freecodecamp.org/t/show-local-weather-api/53140/14 "2017-01-25T18:31:46Z")

</div>

That’s not particularly a lot of code - there’s very little there and a decent amount going on.

It starts with a check to see if we even need to load the data, if not, it early returns and done.

If the data does need to be loaded, it calls the load function which returns a promise. When that promise resolves, the data is updated in an in memory cache. Then finally finally calls to execute callbacks and resolve a promise which allow external code to know that the data is available.

So … load, update/cache, callback/resolve.

Quite simple.

But, if that seems overly long and complex, it can be boiled down to …

```auto

const global_data = { 
	'dataFromServer': null
};

const url = '... some url that returns JSON data';

fetch( url )
	.then( ( response ) => response.json() )
	.then( ( json ) => global_data.dataFromServer = json );
	

```

Now your response is available globally. Of course other code won’t know the data has been loaded unless you create a function that returns a promise or executes a callback … which, if you look above, is all that the loadCollection function I posted is really doing.

---

<div class="post-metadata">

**Author:** ![spoonhonda](https://sea3.discourse-cdn.com/freecodecamp/user_avatar/forum.freecodecamp.org/spoonhonda/32/29794_2.png) [@spoonhonda](https://forum.freecodecamp.org/u/spoonhonda)\
**Post date:** [January 27, 2017, 2:16am UTC](https://forum.freecodecamp.org/t/show-local-weather-api/53140/15 "2017-01-27T02:16:46Z")

</div>

I guess it’s all relative. But 17 lines of code compared to one line of code is a pretty big difference. But your last solution of 6 lines of code makes me feel a bit better. haha

I guess I’m just speaking out of my ignorance and lack of experience here. I mean, it seems like JavaScript should have something like your 17 lines of code already built into it and it would work nice and simple in one line of code. Maybe something like this:  
`var myJsonObject = JSON.parse('url': file.json);`

Anyways, I’ll try your code out and probably end up using it from now on. I don’t fully understand it yet but seems like it’s pretty solid. Thanks!

---

<div class="post-metadata">

**Author:** ![ILM](https://sea3.discourse-cdn.com/freecodecamp/user_avatar/forum.freecodecamp.org/ilm/32/363239_2.png) [@ILM](https://forum.freecodecamp.org/u/ILM)\
**Post date:** [June 1, 2021, 2:37pm UTC](https://forum.freecodecamp.org/t/show-local-weather-api/53140/16 "2021-06-01T14:37:07Z")

</div>

Closed on June 1, 2021, 2:37pm UTC


