I'm working on practicing with the openweathermap api. I have a coordinate object with keys lat & lon which are equal to a string. When I pass that coord obj into another function and try to concat those strings with the api call string they become undefined. I thought I made the scope of these variables global but it doesn't seem to be the case. Can someone tell me what is incorrect about this code
var apikey = '9575f3355ae129dc91424b5712a7695e';
var coords = {};
var accessOWM='';
function myLocation(){ navigator.geolocation.getCurrentPosition(function(position) {
coords.lat = (Math.round(position.coords.latitude*100)/100).toString();
coords.lon = (Math.round(position.coords.longitude*100)/100).toString();
});
}
function changeAccess(coordObj, key){
console.log(coordObj);
accessOWM ='http://api.openweathermap.org/data/2.5/forecast?lat='+coordObj['lat']+'&lon='+coordObj['lon']+'&APPID='+key;
}
myLocation();
console.log(coords);
changeAccess(coords, apikey);
console.log(accessOWM);
That's because getCurrentPosition method is asynchronous. This mean that getCurrentPosition's callback is not invoked at the moment of calling changeAccess function. So you have to place changeAccess call into getCurrentPosition's callback:
function myLocation() {
navigator.geolocation.getCurrentPosition(function(position) {
coords.lat = (Math.round(position.coords.latitude*100)/100).toString();
coords.lon = (Math.round(position.coords.longitude*100)/100).toString();
});
changeAccess(coords, apikey);
}
You have an issue with async code. navigator.geolocation.getCurrentPosition(successCallback) function is an asyncronious function, the successCallback will not be executed immedeately, but with some delay. That is why when you call console.log(coords) and changeAccess(coords, apiKey), the coords are not defined yet. You need to call these functions (and the last one) from inside the .getCurrentPosition() callback.
Since coords is declared in the parent scope of changeAccess, you don't need to pass coordObj into changeAccess. Have you tried:
accessOWM ='http://api.openweathermap.org/data/2.5/forecast?lat='+ coords.lat + '&lon=' + coords.lon + '&APPID='+key;
Either
var apikey = '9575f3355ae129dc91424b5712a7695e';
var accessOWM;
function round(v){ return Math.round(v*100)/100 }
function myLocation(){
navigator.geolocation.getCurrentPosition(function(position){
changeAccess(position.coords);
});
}
function changeAccess(coords){
console.log(coordObj);
accessOWM ='http://api.openweathermap.org/data/2.5/forecast?lat=' + round(coords.latitude) + '&lon=' + round(coords.longitude) + '&APPID=' + apikey;
console.log(accessOWM);
}
myLocation();
Or
var apikey = '9575f3355ae129dc91424b5712a7695e';
var accessOWM = myLocation().then(changeAccess);
accessOWM.then(function(v){
console.log(v);
})
function round(v){ return Math.round(v*100)/100 }
function myLocation(){
return new Promise(function(resolve){
navigator.geolocation.getCurrentPosition(function(position){
resolve(position.coords);
});
});
}
function changeAccess(coords){
return 'http://api.openweathermap.org/data/2.5/forecast?lat=' + round(coords.latitude) + '&lon=' + round(coords.longitude) + '&APPID=' + apikey;
}
Related
[update]
I am using javascript to get data and display it. i created 2 functions, DATA and DISP. i then call DATA first, then call DISP...and am having trouble getting the data from fn DATA to be available globally for later. [i will use it on a weather map]
So i have tried to update with the suggestions, and although i can now force the order using ASYNCH, I still get temp=0 when accessed later, yet it displays fine insided the DATA routine.
---why isnt the global variable TEMP being changed in setup, so i can later display it by an alert with temp= what the temp is, and not temp=0
... note that it only works if i call the disp function inside of the setup, but i cant do this if i want to call multiple APIs to multiple cities
===== so here is the code===
var temp=0; //global
var longitude=0
function DATA()
{
alert(" in DATA ")
//function getWeather() {
let temperature = document.getElementById("temperature");
let description = document.getElementById("description");
let location = document.getElementById("location");
let api = "https://api.openweathermap.org/data/2.5/weather";
let apiKey = "f146799a557e8ab658304c1b30cc3cfd";
location.innerHTML = "Locating...";
navigator.geolocation.getCurrentPosition(success, error);
function success(position) {
latitude = position.coords.latitude;
longitude = position.coords.longitude;
let url =
api +
"?lat=" +
latitude +
"&lon=" +
longitude +
"&appid=" +
apiKey +
"&units=imperial";
fetch(url)
.then(response => response.json())
.then(data => {
// console.log(data);
temp = data.main.temp;
temperature.innerHTML = temp + "° F";
//DISP() // only works here
location.innerHTML =
data.name + " (" + latitude + "°, " + longitude + "°) ";
description.innerHTML = data.weather[0].main;
});
}
function error() {
location.innerHTML = "Unable to retrieve your location";
}
}
//getWeather()
//}
function DISP()
{
alert("disp temp in disp "+ temp)
tempi.innerHTML =temp;
}
async function delayedGreeting() {
DATA()
DISP()
}
delayedGreeting();
try to fix :
function displaydata(data){
...}
Also if you are working with async functions ( maybe when you try to get data from the web) make sure you use await .
await holds the process until it get's the promise back.
Also it might be helpful the add some more of the code .
I'm building a project that finds the geolocation from the browser, then uses the coordinates to get data from the Dark Sky API (https://darksky.net/dev/).
I am able to get the geolocation from the browser, but am having trouble calling the JSON object once I get the geolocation. I understand that getting the geolocation is "asynchronous" and runs at the same time as my other code, and I can't seem to figure out a way around it.
Am I'm doing something wrong? It never seems to runs the: $.getJSON part.
All the #test htmls are for my reference to see where my code is going wrong. #test4 never runs, but #test3 does.
P.S. I've kept the API key hidden for my question, hence the KEY characters in the url. The myJson variable does concatenate a proper url to retrieve the JSON object.
Any help would be deeply appreciated!
var myLat;
var newMyLat;
var myLong;
var newMyLong;
var myJson;
var functionCall;
$(document).ready(function() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
myLat = position.coords.latitude;
myLong = position.coords.longitude;
newMyLat = parseFloat(myLat).toFixed(4);
newMyLong = parseFloat(myLong).toFixed(4);
$("#test1").html("latitude: " + newMyLat + "<br>longitude: " + newMyLong);
myJson =
"https://api.darksky.net/forecast/KEY/" +
newMyLat +
"," +
newMyLong;
$("#test2").html(myJson);
getJsonData();
}); // end of getCurrentPosition function
} // end of navigator.geolocation function
}); // end of document.ready function
function getJsonData() {
$("#test3").html("getJsonData called");
$.getJSON(myJson, function(data) {
$("#test4").html("JSON retrieved");
}); // end of .getJSON function
} // end of getJsonData function
Answer that worked for this situation:
I just needed to add ?callback=? to the end of my JSON url, making it:
myJson = "https://api.darksky.net/forecast/ee2f66f091ed810afc3bf04adc5fa750/" + myLat + "," + myLong + "?callback=?";
Thank you for all the help!
To be able to push markers to the map i need to have the returned data outside of the querying function, but I cant get the data out or return it from the query, how can i make it a global variable, or how can I return the object so I can access it in the rest of the script (not just in the success: function), any help would be appreciated
var query = new Parse.Query("business_and_reviews");
var results = new Parse.Object("business_and_reviews");
query.get("pLaARFh2gD", {
success: function(results) {
console.log(results["attributes"]["lat"]);
lat = results["attributes"]["lat"];
lng = results["attributes"]["lng"];
myLatLng2 = (lat + "," + lng);
console.log(myLatLng2);
myLatLng = new google.maps.LatLng(myLatLng2);
},
error: function(object, error) {
}
});
//lat = results.get(["attributes"]["lat"]);
console.log(lat);
}
You can create a global object (if you really want) and reference it directly in the success object.
However, I'd personally use callbacks to handle the data for both success and fail.
You'd end up with something along the lines of:
//success callback
function createMap(data){
var latlong = data["attributes"]["lat"] + ',' + data["attributes"]["lng"]
var map = new google.maps.LatLng(latlong);
}
//fail callback
function failure(reason){
console.log(reason)
}
//initialising function used to call the API
function initMap(){
getLatLong(createMap, failure)
}
//handles api with callbacks supplied
function getLatLong(successCallback, failCallback){
var query = new Parse.Query("business_and_reviews");
var results = new Parse.Object("business_and_reviews");
query.get("pLaARFh2gD", {
success: function(results) {
if(typeof successCallback ==='function') {
successCallback(results)
}
},
error: function(object, error) {
if(typeof successCallback ==='function') {
failCallback(error)
}
}
});
}
//call the function
initMap();
I'm using the following code:
function eventListenerTest(event) {
if (document.getElementById('gem_cvo_select_list')) {
var address;
$.getJSON(url, function (data) {
address = data.rows[0];
alert("This gets executed afterwards");
});
alert("This gets executed first");
event.infoWindowHtml = "<b>Address: </b>" + address;
}
}
Problem is the $.getJSON function gets executed after the 'address' variable is used in the infoWindow. Modified the code like this:
function eventListenerTest(event) {
if (document.getElementById('gem_cvo_select_list')) {
var address;
$.getJSON(url, function (data) {
address = data.rows[0];
event.infoWindowHtml = "<b>Address: </b>" + address;
});
}
}
The 'event' object doesn't seem to be accessible this way (nothing is displayed in the Google Maps infoWindow). I figured I should be able to pass 'event' to the function inside the JSON but I have no idea how to accomplish this.
Try this:
function eventListenerTest(event, callback) {
if (document.getElementById('gem_cvo_select_list')) {
var address;
$.getJSON(url, function (data) {
address = data.rows[0];
event.infoWindowHtml = "<b>Address: </b>" + address;
callback();
});
}
}
Then:
eventListenerTest(event, function(){
// you will use updated event object here
});
You should use $.proxy method to make sure that the callback function that gets executed keeps the context of the function creating the Ajax call.
Updated Javascript:
function eventListenerTest(event) {
if (document.getElementById('gem_cvo_select_list')) {
var address;
$.getJSON(url, $.proxy(function (data) {
address = data.rows[0];
event.infoWindowHtml = "<b>Address: </b>" + address;
},this));
}
}
More information: http://api.jquery.com/jQuery.proxy/
Hopefully there is an easy way to do this and my Javascript skills are just lacking. I am wanting to call a function that will get some Facebook posts, add them to an array and return to use elsewhere. Current code is below.
function GetFaceBookStream(name, max) {
FB.init({ apiKey: 'removed for post' });
var lastDate = '2011-04-29Z00:00:00';
var faceBookArray = [];
var faceBookString;
FB.api("/" + name + "/feed", { limit: max, since: lastDate }, function (response) {
var sb = string_buffer();
for (var i = 0; i < response.data.length; i++) {
var post = response.data[i];
sb.append("<li class='facebook'>");
sb.append("<img alt=\"Facebook\" src='Images\\Carousel\\fbIcon.png\' />");
sb.append("<h4>FACEBOOK</h4>\n");
sb.append("<div class=\"from-name\">" + post.from.name + "</div>");
sb.append("<div class=\"time\">" + post.created_time + "</div>");
if (post.message != undefined) {
sb.append("<div class=\"message\">" + post.message + "</div>");
}
sb.append("</li>stringSplitMarker");
}
faceBookString = sb.toString();
faceBookArray = faceBookString.split('stringSplitMarker');
});
return faceBookArray;
}
I realize this set up won't work due to variable scope in Javascript, but this is basically what I'm trying to achieve. Any help will be greatly appreciated!
You're making an asynchronous AJAX request.
The callback only runs after your code finishes.
You need to pass the data back using a callback.
For example:
function GetFaceBookStream(name, max, callback) {
...
FB.api(..., function(response) {
...
callback(something, else);
});
}
You can call the function by supplying a callback to receive the response:
GetFaceBookStream(name, max, function(param1, param2) {
//This code runs later and can use the response.
});