Why Google place AutocompleteService callback not getting executed? - google-maps

I have following code for place AutocompleteService() as:
var strAddr = '';
if (address.value != "") {
var service = new google.maps.places.AutocompleteService();
service.getQueryPredictions({ input: address.value }, function (predictions, status) {
console.log('1');
if (status == google.maps.places.PlacesServiceStatus.OK) {
console.log('Original Response: ' + predictions[0].structured_formatting.secondary_text);
strAddr = predictions[0].structured_formatting.secondary_text;
}
});
console.log('strAddr: ' + strAddr);
console.log('2');
}
console.log('3');
I am getting response in console as:
strAddr:
2
3
1
Original Response: //gettting matched address here
But it should be:
1
Original Response: //matched address here>
strAddr: //matched address here
2
3
Why the callback not executing in sequence as expected?

The getQueryPredictions function is asynchronous (it's probably happening via AJAX). So you can't guarantee that it will complete before the code immediately after it.
e.g. the call to getQueryPredictions might take perhaps 0.5 seconds. So while that's happening, these two lines will be able to execute immediately:
console.log('strAddr: ' + strAddr);
console.log('2');
You can't rely on strAddr being available in any code that happens outside of your callback function that's waiting for the getQueryPredictions response.

It is not guaranteed that you get this
1
Original Response: //matched address here>
strAddr: //matched address here
2
3
Because this ( new google.maps.places.AutocompleteService(); ) is asynchronous call and your callback can be called at any sequence

Related

Save result to variable?

So I have been developing a note taking app, and I am having some trouble with displaying the username! Normally you would get a result like this:
con.query('SELECT someVariable FROM someColumn', function (result) {
console.log(result)
})
But I would like to save the result to a variable like this:
var variable = '';
con.query('SELECT someVariable FROM someColumn', function (result) {
variable = result
})
console.log("Here is some data: " + variable)
But that obviously wouldn't work. So how can I do this???
The point
How would I save a mySQL result to a variable, so it can be used later in my code? Also Im not an experienced developer so you might have to do a bit more explaining that usual, thanks.
If you're new to Node and/or JavaScript then you've just stumbled on one of the major problems of asynchronous programming. Here's your code as the JavaScript runtime sees it:
// Declare variable
var variable = '';
var callback = function(result) {
variable = result;
};
// This code runs right away
con.query('SELECT someVariable FROM someColumn', callback);
// Then this code runs
console.log("Here is some data: " + variable);
// Then, a thousand years later (from a CPU's perspective) this callback executes
callback(result);
You can see you're jumping the gun here. You can't depend on any behaviour until the callback has run, or in other words, you need to put any dependent behaviour inside the callback.
Since it's 2020 you can also do this with async and await if you're using a Promise-capable library. Your code could look like:
// Assign variable to the result of the query call, waiting as long as necessary
let variable = await con.query('SELECT someVariable FROM someColumn');
console.log("Here is some data: " + variable);
This will be properly sequenced.

cannot return after successful json request [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 5 years ago.
I have made a json call from this type of function and i got the result, But i cannot return this value to another function
get_target_amount(full)
this is my function. after console.log(get_target_amount(full)) result is undefined. what is the reason for this?
function get_target_amount(full) {
var target = '';
var param = {};
param.sub_category_id = full["sub_category_id"];
param.project_month = full["project_month"];
jQuery.post(site_url + '/Progress_project_create/get_target_amount', param, function (response) {
if (response !== null) {
target = response.target_amount;
} else {
target = 'Target amount not found';
}
return target;
}, 'json');
}
The problem here is the asynchronous nature of Ajax calls.
Please move your target variable based code into the callback function you have in the get() function.
function(response){//Write all your code here.}
Currently, the get_target_amount() returns back without waiting for the ajax call to finish. Hence, you get the null value.
You can consider another option like, making you ajax call synchronous.
Then the browser halts/freezes the page till the ajax function completes. This will not be advisable as it makes the user unnecessarily wait for the page to respond.
Also, the return statement you have in your callback function is not referred anywhere

Asynchronous Call in Google Map

Ok, Here is my JS Function :
function GetLatLong() {
var geocoder = new google.maps.Geocoder();
var address = $('#txtAddress').val() + ', ' + $('#txtCity').val() + ', ' + $find('drpState').get_text() + ', ' + $find('drpCountry').get_text();
var result = false;
geocoder.geocode({ 'address': address }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var location = results[0].geometry.location;
$('#hiddenLatLong').val(location);
result = true;
}
else {
alert("Geocode was not successful for the following reason: " + status);
result = true;
}
});
return result;
}
Now, what i want is, i want to return the result once i store the value in hidden field. Here what happens is, i am calling this function on button click, but as the call is asynchronous, it returns false on the click and i cannot get the resultant value in hidden field. Is there any way where i can wait or some work around with which it can be obtained in the hidden field?
The second parameter in the geocode function is a callback function that will be invoked if the geocode results return. So from your given code the hidden value should be set if Google returns a result.
However your GetLatLong() function is completed earlier and therefore returns false. So you should not make your processing dependent on this method return value.

Repeat jQuery JSON request until condition is met

I am trying to repeat a JSON request in jQuery to check the status of a video encoding job until it is completed. "Processing" would be displayed until the job is finished, at which point the video will be displayed.
Would a loop, checking every x seconds to see if "status" equals "finished," be the best solution for this? If so, how would I break free from this loop when the job is finished?
The JSON response while the job is in progress will be nothing more than "processing," when it is finished it will contain things such as the job ID, width, and height.
Any help would be appreciated, thanks!
UPDATE
Here's my final solution thanks to Felix:
var checkStatus = function() {
$.getJSON('json-data.php', function(data) {
if (data.status != 'finished') {
setTimeout(checkStatus, 2000);
} else {
//Sample code to run when finished
$("#statusText").text("Job Complete");
$("#dimensions").text(data.width + 'x' + data.height);
}
});
};
checkStatus();
A loop won't work as the Ajax request is asynchronous.
One way would be to make same kind of recursive call and trigger the Ajax function again from the success callback (maybe after some timeout), if the condition is not met.
Something like (pseudo code):
function check_condition() {
$.getJSON(<url>, function(result) {
if(!result.finished) {
setTimeout(check_condition, 2000);
}
// do something else
}
}
var checkStatusInterval = 30 * 10000; // 30 seconds
var checkStatusFunc = function(){
$.getJSON('getMovieStatus', function(data){
if (data.Incompleted){ // or however you check
checkStatusTimer = setTimeout(checkStatusFunc, checkStatusInterval);
}
});
};
var checkStatusTimer = setTimeout(checkStatusFunc,checkStatusInterval );
To stop:
<input type="button" id="stopchecking" value="Stop Checking..." />
$('#stopchecking').click(function(e){
clearTimeout(checkStatusTimer);
});

Geolocation feedback while accepting the request

the geolocation implementation is quite good and got few steps to observe but only on thing is missing, i guess.
Im not able to see if the user accepted the request or not ( before i get the position object ), i dunno if the user just ignores my request ( during my timeout ) or if the request just get lost ( and the failure callback doesnt get called for no reason ).
It would be useful to set a timestamp when the user accepts the request, i couldnt find anything which gives me that kind of response.
Based on my new understanding of what you are after, you want something like this.
(Tested: in Opera - works, Firefox 3.6 & Chrome 8 - not so much (I need more time to debug))
Scenario:
Page attempts to get location... but user ignores the prompt completely thus there is no (accept or deny) and since the request for the location is never sent, there is no timeout either!
Based on this you may want to add your own logic to handle this scenario. For the sake of this example, I'm going to prototype my own "wrapper" method. (for the picky - I'm not condoning using globals etc. I was just trying to get something to work)
navigator.geolocation.requestCurrentPosition = function(successCB, errorCB, timeoutCB, timeoutThreshold, options){
var successHandler = successCB;
var errorHandler = errorCB;
window.geolocationTimeoutHandler = function(){
timeoutCB();
}
if(typeof(geolocationRequestTimeoutHandler) != 'undefined'){
clearTimeout(window['geolocationRequestTimeoutHandler']);//clear any previous timers
}
var timeout = timeoutThreshold || 30000;//30 seconds
window['geolocationRequestTimeoutHandler'] = setTimeout('geolocationTimeoutHandler()', timeout);//set timeout handler
navigator.geolocation.getCurrentPosition(
function(position){
clearTimeout(window['geolocationRequestTimeoutHandler']);
successHandler(position);
},
function(error){
clearTimeout(window['geolocationRequestTimeoutHandler']);
errorHandler(error);
},
options
);
};
function timeoutCallback(){
alert('Hi there! we are trying to locate you but you have not answered the security question yet.\n\nPlease choose "Share My Location" to enable us to find you.');
}
function successCallback(position){
var msg = '';
msg += 'Success! you are at: ';
msg += '\nLatitude: ' + position.coords.latitude;
msg += '\nLongitude: ' + position.coords.longitude;
msg += '\nAltitude: ' + position.coords.altitude;
msg += '\nAccuracy: ' + position.coords.accuracy;
msg += '\nHeading: ' + position.coords.heading;
msg += '\nSpeed: ' + position.coords.speed;
alert(msg);
}
function errorCallback(error){
if(error.PERMISSION_DENIED){
alert("User denied access!");
} else if(error.POSITION_UNAVAILABLE){
alert("You must be hiding in Area 51!");
} else if(error.TIMEOUT){
alert("hmmm we timed out trying to find where you are hiding!");
}
}
navigator.geolocation.requestCurrentPosition(successCallback, errorCallback, timeoutCallback, 7000, {maximumAge:10000, timeout:0});
The concept is to set up a timer first (defaults to 30 seconds if not set). If the user doesn't do anything before the timer expires, a timeoutCallback is called.
Notes:
Some UI's (e.g. iPhone/iPad/iPod Safari) may make the Allow/Deny prompt modal - thus the user can't really continue until they pick something (I'd suggest to leave these users alone and let the default UI handle things
If the user Allows the request (late), the timeout may still fire before the response comes back - I don't think there is anything you can do about this
Code above is an example only... it needs cleaning up.
It is part of the Geolocation API:
// navigator.geolocation.getCurrentPosition(successCallback, errorCallback, options);
navigator.geolocation.getCurrentPosition(
function(position){
//do something with position;
}, function(){
//handle condition where position is not available
//more specifically you can check the error code...
//error.code == 1
if(error.PERMISSION_DENIED){
alert("you denied me! ");
}
});
If you specify the errorCallback... then you can track if the user has declined to provide access.
Possible error codes include:
error.PERMISSION_DENIED (numeric value 1)
error.POSITION_UNAVAILABLE (numeric value 2)
error.TIMEOUT (numeric value 3)
Tested it successful in FF 3.5, Opera 10.6, Chrome8, IE6-8..
var succeed = function(obj) {
navigator.geolocation.received = true;
!navigator.geolocation.timedout?alert('GOT YAH'):alert('GOT YAH but user was to slow');
};
var failed = function(obj) {
navigator.geolocation.received = true;
!navigator.geolocation.timedout?alert('just failed'):alert('failed and user was to slow as well, tzz ._.');
};
var timedout = function() {
navigator.geolocation.timedout = true; // could be used for other callbacks to trace if its timed out or not
!navigator.geolocation.received?alert('Request timed out'):null;
}
// Extend geolocation object
if ( navigator.geolocation ) {
navigator.geolocation.retrievePermission = function retrievePermission(succeed,failed,options,timeout) {
this.received = false; // reference for timeout callback
this.timedout = false; // reference for other callbacks
this.getCurrentPosition.apply(this,arguments); // actual request
// Trigger timeout with its function; default timeout offset 5000ms
if ( timeout ) {
setTimeout(timeout.callback,timeout.offset || 5000);
}
}
// New location request with timeout callback
navigator.geolocation.retrievePermission(succeed,failed,{},{
offset: 10000, // miliseconds
callback: timedout
});
// Awesome thingy is not implemented
} else {
alert('geolocation is not supported');
}
With that workaround we know if the request timedout, even when the succeess / failure callback get called afterwards.