Javascript Local Variable Not Updated - javascript

I have coded this function to detect and update postLat and postLon variables.
function searchAddSubmit(){
var shopId = 1; //random number to test the function
var postLon, postLat;
var shopTime = $("#selected-search-result-minutes").val();
navigator.geolocation.getCurrentPosition(function(position){
postLat=position.coords.latitude;
postLon=position.coords.longitude;
console.log(postLat);
console.log(postLon);
console.log('reun');
},function(error){});
console.log(postLat+" 1231");
console.log(postLon+" 1231");
$.ajax({
type: "POST",
url: "search-add-process.php",
cache: false,
dataType: "json",
data:{
id: shopId,
time: shopTime, //this value is taken from a form input
lat: postLat,
lon: postLon
},
success: function (data) {
if(data.error === true) {
alert(data.msg);
} else {
alert(data.msg);
//remove output when successful
}
}
});
}
I used Chrome's Javascript Console tool to examine the variables (as printed with console.log()) and this is the result:
undefined 1231
undefined 1235
1.2957797
103.8501069
ruen
Coming to this point, I have these questions:
Why are the variables postLon and postLat are not updated? In fact, the undefined variables are passed over to search-add-process.php in the ajax block, not the actual values.
Why navigator.geolocation.getCurrentPosition() function runs after the console.log(postLat+" 1231") line? Correct me if I am wrong, I always assumed that Javascript would execute line by line.

You first tell the Geolocation API to try to find the current position of the user, and you let it go and search while you do the rest of your work. This is called Asynchronous Execution. In other words, you let the Geolocation API take its time to search and find the place of the user, while you do the rest of your job (rest of your code is getting executed). Then when the API found the position, it executes the function you've passed to it.
Take the code of ajax into the success callback and everything would be fine.

Place the whole $.ajax({...}); call within the getCurrentPosition callback function;
e.g. place it directly before or after the line console.log('reun');

Related

getJson returns undefined value instead of Json object

I am trying to use simple getJson call to get Json object from server.
On server side everything looks good. Json is created and returned:
But on the front-end my object is not mapped to returned Json from server. It is undefined in first call and that value and then it goes one more time through getJson and returns real object.
This is my code:
btnSaveNewMeeting.onclick = function () {
var vm = {
'Title': $('#eventTitle').val(),
'StartAt': $('#startdatepicker').val() + ' ' + $('#starttimepicker').val(),
'EndAt': $('#enddatepicker').val() + ' ' + $('#endtimepicker').val()
}
var meetings = GetAllScheduledMeetings();
if (CheckIfMeetingsAreOverlapping(vm.StartAt, vm.EndAt, meetings)) {
addNewMeetingModal.style.display = "none";
$.ajax({
type: 'POST',
url: "/Meeting/Create",
data: vm,
success: function () {
$('#calendar').fullCalendar('refetchEvents');
}
});
ClearPopupFormValues();
}
}
So I want to get value from GetAllScheduledMeetings(); and put it in meetings object.
var meetings = GetAllScheduledMeetings();
function GetAllScheduledMeetings() {
$.getJSON("/Meeting/GetAllScheduledMeetings", function (result) {
return result;
});
}
So GetAllScheduledMeetings() should only make a call to server and return result. But that doesn't happened.
When I debug in console of a browser what is happening is this:
1. on button click GetAllScheduledMeetings() gets invoked.
2. getJson makes a call to server and json object is created there and returned.
3. it goes back to front-end but skips whole return result; part and returns undefine value to var meeting = GetAllScheduledMeetings();
4. I get few exceptions because meeting is undefine
5. GetAllScheduledMeetings() gets called again for some reason, after all of this has happened and in this call result gets real values from server.
Does someone knows why is this happening? Why two calls are made and why in the first call I do not get data from server?
GetAllScheduledMeetings never returns anything (so, returns undefined) and "is async", so, at the moment of execution, when using meetings, there is a very high probabilty for the variable to be undefined.
You'll need to recode GetAllScheduledMeetings to pass you all "if block" as a callback or use any other way to work with async code (Promises for instance).
function GetAllScheduledMeetings() {
$.getJSON("/Meeting/GetAllScheduledMeetings", function (result) { // This anonymous function is called asynchronously and returns result *in the blue*
return result;
});
// GetAllScheduledMeetings doesn't specify a return value so it's retVal is undefined
}
SOLUTION:
Since $.getJSON or $.ajax calls are asynchronous by default all you need to do is make them synchronous by adding: async: false to call definition.

Wait for data from external API

I am attempting to interface with the Google Maps API marking locations based on latitude and longitude data. I would also like to get time zone information based off of this latitude and longitude. To do this, I am using another external API that takes in the latitude and longitude and returns the time off-set. My issue, however, is that this time data returns after the page is loaded.
What is the best way to then add this information to the page after the page has loaded for the user? I started out thinking about using postback, but after doing some research, I don't think that's the right method for my problem.
In browsers, JavaScript allows you to contact a server after a page is loaded. This is known as an asynchronous request, the first 'A' in 'AJAX' (Asynchronous Java and XML).
The X can be a bit of a misnomer, as people will happily pass whole chunks of HTML, or JSON (AJAJ?) or other forms of data instead of XML through this mechanism.
I would always use a framework (my personal choice being JQuery) to perform the operation, as the framework writers will have done the job of making it all work cross-browser for you.
You could use this:
http://api.jquery.com/jQuery.get/
or if the return data is JSON,
http://api.jquery.com/jQuery.getJSON/
This function, part of JQuery, will execute a callback function once the data is loaded. Your callback function can then use the JQuery selectors to find and update the elements in question.
If you update your question with specific code examples I can be more specific with my response.
Edit after seeing code example:
It looks like your problem is actually one of working out the order of code execution. Your code follows this pattern (somewhat simplified and a touch rearranged):
var startTimeZone;
jQuery(document).ready(function($) {
$.ajax({
url: "http://www.worldweatheronline.com/feed/tz.ashx?key=SecretKey&q=" + start_locale + "&format=json",
dataType: "jsonp",
success: function(parsed_json) {
startTimeZone = parsed_json.data.time_zone[0].utcOffset;
console.log("Callback: " + startTimeZone);
},
error: function(parsed_json) {
}
});
});
console.log("Main:" + startTimeZone);
Firstly, there isn't a need to wrap the ajax command in the document ready callback - that only needs to be done once for the whole of your code, around wherever the entry point is. (I assume that it was an attempt to delay the execution until after the following code.) (There is more to learn here as well - JQuery gives you more than one event to help initialise your code and work with the DOM, see window.onload vs $(document).ready() for a brief description)
If you ran the snippet above, you'd find that the console log would probably show:
Main: Undefined
Callback: [StartTimeZone]
where [StartTimezone] is the response from the server. The ajax command is asynchronous, meaning it goes off and does its thing, taking as long as it needs, leaving the code after it to run as if nothing had happened. When it's finished it calls the 'success' or 'error' callback appropriately. So the 'main' console log is called before the variable has been defined. After that, the callback is hit by the response to the ajax call - so the StartTimeZone is output.
If you're new to callbacks or used to a language that doesn't support them or use them very often (like PHP), you may expect or want the code to pause at the ajax call, then run the callback, then carry on with the rest of the code. Obviously this isn't the case.
In this simple situation I would simply move the code to process the timezone into the callback, but your code has a further wrinkle - you need two values, which you seem to need to retrieve with separate calls.
In this case, we need to make sure we have both values before we run the code that uses them. How can we do this?
A simple solution would be:
var startTimeZone;
var endTimeZone;
$.ajax({
url: "http://www.worldweatheronline.com/feed/tz.ashx?key=SecretKey&q=" + start_locale + "&format=json",
dataType: "jsonp",
success: function(parsed_json) {
startTimeZone = parsed_json.data.time_zone[0].utcOffset;
getEndTimeZone();
},
error: function(parsed_json) {
//console.log("Error: " + parsed_json);
}
});
function getEndTimeZone() {
$.ajax({
url: "http://www.worldweatheronline.com/feed/tz.ashx?key=SecretKey&q=" + end_locale + "&format=json",
dataType: "jsonp",
success: function(parsed_json) {
endTimeZone = parsed_json.data.time_zone[0].utcOffset;
console.log(endTimeZone);
processTimeZones();
},
error: function(parsed_json) {
//console.log("Error: " + parsed_json);
}
});
}
function processTimeZones() {
var timeZoneDifference = (endTimeZone * 3600000) - (startTimeZone * 3600000);
// Do the rest of your processing here
}
Functions aren't run until they are called. Also, functions in JavaScript have access to the variables in their containing scope (this means that the functions have access to startTimeZone and endTimeZone, which are defined outside the functions themselves.)
The code above will call getEndTimeZone on success of the first ajax call. getEndTimeZone then uses an ajax call to get the end time zone, then calls the process function on success. This function definitely has access to the variables you need.
Of course, we're waiting in a queue now for two requests to be processed. We could speed things up a little by calling both at the same time, calling the process function with both, then figuring out if we have the data we need before doing the processing:
var startTimeZone;
var endTimeZone;
$.ajax({
url: "http://www.worldweatheronline.com/feed/tz.ashx?key=SecretKey&q=" + start_locale + "&format=json",
dataType: "jsonp",
success: function(parsed_json) {
startTimeZone = parsed_json.data.time_zone[0].utcOffset;
processTimeZones();
},
error: function(parsed_json) {
//console.log("Error: " + parsed_json);
}
});
$.ajax({
url: "http://www.worldweatheronline.com/feed/tz.ashx?key=SecretKey&q=" + end_locale + "&format=json",
dataType: "jsonp",
success: function(parsed_json) {
endTimeZone = parsed_json.data.time_zone[0].utcOffset;
console.log(endTimeZone);
processTimeZones();
},
error: function(parsed_json) {
//console.log("Error: " + parsed_json);
}
});
function processTimeZones() {
if (startTimeZone != undefined && endTimeZone != undefined)
{
var timeZoneDifference = (endTimeZone * 3600000) - (startTimeZone * 3600000);
// Do the rest of your processing here
}
}
Whichever ajax call returns first will call the process function. However, one of the variables will be undefined so the if condition will fail and the function will silently return. When the second result comes in, both variables will be set. Now the if condition will be met and the processing code will run.
There are 1001 ways to skin the proverbial cat, but these should hopefully get you started using the callbacks effectively.
Of course, all this is ignoring the fact that you've put the ajax calls in a for loop. Things could get funky if each iteration of the processing you need to do is dependent on the order it happens - the ajax calls could return in potentially any order. As you're plotting a route, this may well be the case.
If so, you could split your code into two phases - a loading phase and a processing phase. Run all the callbacks in the loading phase, then when you have all the data move to the processing phase and place the markers on the map. You could store the data in an array of objects.
There are a few ways to detect the end of the loading phase. One would be a counter that you increment every time you make an ajax call and decrement every time you get a success. You'd be able to create a loading progress bar using the same counter.
Also you could display a message to the user if any of the calls failed, with a link to restart the process. (Trivially this would reload the whole page, but you could restart the loading stage.)
HTH. By all means shout if you need further help.

maintain value of variable outside function in javascript?

I try to manipulate a variable inside a function. But it seems to forget the values once I exit the function, eventhough the variable is declared outside the function.
The essential code:
var posts = {};
// Perform a data request
// skjutsgruppens-page
$.oajax({
url: "https://graph.facebook.com/197214710347172/feed?limit=500",
*SNIP*
success: function(data) {
$.extend(posts, data);
}
});
// Gruppen
$.oajax({
url: "https://graph.facebook.com/2388163605/feed?limit=500",
*snip*
success: function(data) {
$.extend(posts, data);
}
});
The oajax retrievies data from facebook. I want to make a variable that contains the data from both oajax methods.
The actual code: http://eco.nolgren.se/demo/resihop/#
The issue is likely that the success function executes at an arbitrary time in the future--unless you specifically access posts after you know the success function has executed, you will receive undefined results, completely dependent on function and access timing.
The best approach is to handle this correctly by doing necessary work inside in the success function, or use something like jQuery's .when function.

getJSON to string then loop through string

I have the following code which is included in a keypress function:
$.getJSON('dimensions.json', function(data) {
$.each(data, function(index) {
$('#div1').append(index);
});
});
I'm trying to first get the JSON string, save it in a variable and then run the each(). I want to basically separate the each() to be unlinked to the getJSON() function because I don't want it to fetch the json file for every keypress.
I've tried this, but it didn't work:
var JSONstr = $.getJSON('dimensions.json');
$.each(JSONstr, function(index) {
$('#div1').append(index);
});
In your first example, you do $.each in the callback. The callback is executed by some other callback after there result is received, while $.getJSON returns immediately without waiting for the result (since there is no blocking in JavaScript by design).
Therefore the code in your second example can never work: the $.each begins before any result is received from the web server, probably even before the request is sent. Whatever the return value of $.getJSON is, it can't, by the design of JavaScript, be the result of AJAX request.
UPD: Saw your comment, now I understand what you wanted to do. Here's a simple example of how to do this:
function ActualHandler(data) {
$.each(data, function(index) {
$('#div1').append(index);
});
}
function KeypressHandler() {
if (window.my_data) { // If we have the data saved, work with it
ActualHandler(window.my_data);
}
else { // Otherwise, send the request, wait for the answer, then do something
$.getJSON('dimensions.json', function(data) {
window.my_data = data; // Save the data
ActualHandler(data); // And *then* work on it
});
}
}
Here, the ActualHandler is not launched before the data is received, and once that happens, all subsequent clicks will be handled immediately.
The downside in this particular case is that if user clicks again while the first request is running, one more will be sent. But to fix that you would need to maintain some queue, which is kind of out of scope here.
You fell into the asynchronous trap. Your $.each() function doesn't wait for your $.getJSON() call to get the data. You can get around this by using the good 'ol $.ajax() function. Like this:
function processJSON(data) {
$.each(data, function(index) {
$('#div1').append(index);
});
}
$.ajax({
url: 'dimensions.json',
dataType: 'json',
async: false,
success: processJSON(data)
});

Using Javascript / JQuery to access an array built from an external XML file

I hope this is not too much of a newbe question but I've been pulling my hair out for a while now so thought I'd give in and ask for my first piece of advice on here.
I'm trying to read an external xml file using javascript / jQuery / ajax and place the retrieved data into an array so that I can then reference it later.
So far I seem to be doing everything right upto the point I put the data into the array but then I'm struggling to to read the data anywhere other than inside the function where I create it. Why am I not able to access the Array from anywhere other than in that function?
Here is my code...
Please help!!
$.ajax({
type: "GET",
url: "data.xml",
dataType: "xml",
success: do_xmlParser
});
function do_xmlParser(xml)
{
var myArray = new Array();
$(xml).find("tag").each(function ()
{
myArray.push($(this).find("innerTag").text());
});
console.log("inside "+myArray); // This outputs the array I am expecting
return myArray; // is this right???
}
console.log("outside: "+myArray); // This does NOT output the array but instead I get "myArray is not defined"
You're defining do_xmlParser as a callback to an asynchronous function (success of the jquery ajax call). Anything you want to happen after the ajax call succeeds has to occur within that callback function, or you have to chain functions from the success callback.
The way you have it now, the actual execution of code will go:
ajax -> file being requested -> console.log ->
file transfer done -> success handler
If you're doing some critical stuff and you want the call be to synchronous, you can supply the
async : false
setting to the ajax call. Then, you should be able to do something like this:
var myArray = [],
do_xmlParser = function (xml)
{
$(xml).find("tag").each(function ()
{
myArray.push($(this).find("innerTag").text());
});
};
$.ajax({
type: "GET",
url: "data.xml",
dataType: "xml",
success: do_xmlParser,
async: false
});
console.log("outside: " + myArray);
The async option doesn't work for cross-domain requests, though.
NOTE
I don't recommend doing this. AJAX calls are supposed to be asynchronous, and I always use the success callback to perform all of the processing on the returned data.
Edit:
Also, if you're into reading... I'd recommend jQuery Pocket Reference and JavaScript: The Definitive Guide (both by David Flanagan).
look close and you will see. You are actually firing up an array that dosen't exist. You have declared myArray inside function. Try do something like this.
console.lod("outside :"+do_xmlParser(xml)); // I think that when you merge a string and an array it will output only string, but I can be wrong.

Categories

Resources