This question already has answers here:
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Closed 6 years ago.
When I run this, the variable elevationPoint is undefined on the first alert. I noticed by accident that it works on the second alert. Why is that?
var elevator = new google.maps.ElevationService();
var coordinates = new google.maps.LatLng(closestLat , closestLng);
var pointElevation;
elevator.getElevationForLocations({
'locations':[coordinates]
}, function (results, status) {
if (status == google.maps.ElevationStatus.OK) {
// Retrieve the first result
if (results[0]) {
pointElevation = results[0].elevation;
} else {
alert('No results found');
}
}
else {
alert('Elevation service failed due to: ' + status);
}
});
alert(pointElevation);
alert(pointElevation);
The fact that you pass a callback to API that you are using makes me think that it is asynchronous.
When you make the first alert the asynchronous task has not completed yet . By the time the second alert fires the callback has completed and you get the expected value on the variable that youbexoex. Try moving the alert inside the function you pass to the API and it should work.
Regards
Edit to clarity the blocking/non-blocking topic
Functions requiring callbacks are usually asynchronous,and they run on a separate thread called the eventLoop. The code is executed immediately after evaluation, so your API call fires immediately and it is placed on the event loop. When the first alert is reached the asynchronous operations are already on the eventLoop, so although the alert is blocking it can not block the code running on a separate thread. When the second alert is executed the asynchronous code has already completed and the callback executed ,that's why you can see the value on the second alert .
I recommend you investigate about the event loop and how it works
This is a fantastic visual explanation https://m.youtube.com/watch?v=8aGhZQkoFbQ
Because pointElevation is defined inside an asynchronous call getElevationForLocations(). By chance the 2nd alert works it is because the async call has finished by then, but it is not guaranteed.
Related
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed last year.
Now I am using JavaScript function coded as follows:
self.fillSelect = function (key) {
html = "<option value =''>choose</option>";
self.getGroupOptions(key, function (res) {
for (let a = 0; a < res.length; a++) {
html += "<option value = '" + res[a].Code_Name + "'>" + res[a].Code_Name + "</option>";
}
}, function (err) {
});
return html;
}
As I know or understand the html variable is a global variable and can be accessed in any place in the function.
In this function this logic happens after the return statement.
This function just returns
<option value =''>choose</option>
then enters the loop with no result...why is that happening??
self.getGroupOptions()
This function is a jQuery AJAX request to get options from database
TLDR
You should learn about javascript asynchronous functions and callbacks. The for loop that populates the html is inside a function that gets called later, in async.
Long version
JavaScript is single threaded, that means that there is a single line of execution and things cannot happen "at the same time" in two places of a JS software, be it a page or a node JS application.
To work around this "feature", in JS is very common to run async operations providing a callback.
The underlying system (in this case, the browser) will perform the operation (in this case, an AJAX call) and then "call back" your code by invoking a provided function.
This is what is happening in this case, the call to AJAX happens later, your code return before.
Then when the AJAX call happens, you call is called as part of the "call back", the for loop executes, the html variable is filled, but at that moment is too late to return it.
You should return a Promise and register a callback on that promise to be able to retrieve the html content later, when all the AJAX stuff and callback is completed.
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Closed 6 years ago.
When getting data from a text file, it seems to take a while. With the first console.log the result is undefined, after waiting some time and then running console.log the data shows.
var msg;
$.get("./whazzup.txt", function(text) {
msg = text;
});
console.log(msg);
setTimeout(function(){ console.log(msg); }, 3000);
How would I go about only running code once the callback is complete?
Just move the console.log() into the "done" callback function because you can't know exactly when or if it will complete. This is the point of the "done" callback function - - to defer work that needs to be done after a successful call has been made.
JavaScript promises (or JQuery deferreds) could also be used to disconnect the callback(s) from the initial AJAX request for more flexibility, but the nature of AJAX stays the same.
$.get("./whazzup.txt", function(text) {
// This function will only be executed when the AJAX call has successfully completed
msg = text;
console.log(msg);
});
// This one was working, because you are basically telling the JavaScript
// runtime to wait 3 seconds (at least) before writing the message and by
// that time the AJAX call has completed. But, this technique is not
// reliable because there may be times when the AJAX call hasn't completed
// after 3 seconds. You just can't know how long it will take.
setTimeout(function(){ console.log(msg); }, 3000);
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 4 years ago.
I am relative new to node.js and I ran into a problem where a function is returning undefined. I use console.log to make sure that it returns the proper value and it does. But in the script that makes the call to the function shows as undefined. I think this may be an issue with async programming? I am trying to learn more on how promises work in node.js. What am I doing wrong?
The reason why I believe that it is a problem with async is because console.log is printing to the console undefined before the console.log in getCurrentFrameName();. var name is being assigned undefined.
frameHandler.switchToFrame('top_page');
var name = frameHandler.getCurrentFrameName();
console.log(name);
The console.log in this method prints to the console after the console.log in the code above. The value printed to the console of name is top_page.
this.getCurrentFrameName = function()
{
driver.executeScript('return self.name').then(function(name) {
console.log(name);
return name;
});
};
You can do this:
this.getCurrentFrameName = function(callback) {
driver.executeScript('return self.name').then(function(name) {
return callback(name);
});
};
and then call it like this:
frameHandler.getCurrentFrameName(function(name) {
console.log(name);
});
this will fix your problem, but yes, is a sync problem.
Yes, this is an issue with asynchronous programming. You cannot return a value from an asynchronous callback.
This is because the callback waits for the asynchronous script to execute, and so, node immediately passes control to the next line after the callback.
In your case, console.log(name); gets called before the callback is executed. Hence, the undefined.
The simplest solution to the current situation is to perform the necessary computations within the callback itself.
However, in more complicated situations (such as, callback within callback) you can easily end up with what is known as callback hell.
There are several ways to deal with callback hell: one of them is something called Promise.
What a Promise does essentially, is that it brings a sense of linearity to the code, thus making it easier to understand and maintain.
In your case, you can do this:
this.getCurrentFrameName = function() {
var myPromise = driver.executeScript('return self.name');
myPromise.then(function(name) {
// Do all computation with `name` here
});
};
This question already has answers here:
Hidden threads in Javascript/Node that never execute user code: is it possible, and if so could it lead to an arcane possibility for a race condition?
(3 answers)
Closed 7 years ago.
In many js examples, I see calls to functions doing tasks asynchronous, for example:
var objectStoreTitleRequest = objectStore.get(title);
objectStoreTitleRequest.onsuccess = function() {
// Grab the data object returned as the result
var data = objectStoreTitleRequest.result;
}
(This example is based on https://developer.mozilla.org/en-US/docs/Web/API/IDBRequest/onsuccess)
I wonder how this could work if the async execution finished before the onsuccess handler is set. I expected that event handlers added before execution of the async function, but all js examples add handlers after the call (in this case: get()). How is this internally solved? And how can I implement a custom object which provides a similar API? I think this must be something like
{self.result = do_work(); wait for onsuccess handler is set...; if handler_avail -> self.onsuccess(); }
Because Javascript is strictly single-threaded, asynchronous operations can only run their callbacks once other code has finished running.
Therefore, it is impossible for the request to finish between two lines.
This is exactly the reason why you should never call a callback function / event handler synchronously.
For example, the following code is wrong:
function async(val, cb) {
if(val < 0) {
cb();
}
else {
setTimeout(cb, val);
}
}
And must instead be implemented similar to:
function async(val, cb) {
if(val < 0) {
setTimeout(cb, 0);
}
else {
setTimeout(cb, val);
}
}
I understand that Javascript doesn't have multiple threads, but I'd like to know if the following code has any chance of breaking. My understanding is that unless an asynchronous function is called, such as setTimeout or an AJAX call, that once a block of code starts executing there's no way for it to pause until it completes or does call an asynchronous function.
Basically, users select multiple checkboxes and then hits a button that executes AJAX processing of their selections. My goal is to have a "Saving..." icon that stays only until all the AJAX processes are complete, and after all are finished display a success message.
Barring any AJAX errors, so long as the callback function in the jQuery.post executes in its entirety without interruption, I don't see how the if(numProcessed == toProcess) would ever execute more than once or less than once. But if two AJAX callbacks get into the callback function, both increment the numProcessed counter before either get to the following if, then it seems that the code inside would be executed twice.
var numProcessed = 0;
var checkedBoxes = jQuery("input[type=checkbox]:checked");
var toProcess = checkedBoxes.size();
checkedBoxes.each(function() {
jQuery.post('somepage.php',{...},function(results) {
numProcessed++;
if(numProcessed == toProcess) {
jQuery("#saving-message").remove();
jQuery("#feedback-panel").text('Successfully processed all selections.');
}
}
}
There is only one thread in JavaScript so every function that want to be execute is put in stack and have to wait until all others are execute. In your case "each" is the first function in the stack, so every callback function have to wait and will be execute in the order they put on the stack.
After all "numProcessed == toProcess" could only one time be true.
The rx.net team has introduced rx for javascript. Reactive extension are for asynchronous programming. they have also written for rxjs for jquery too. My be that suite your need http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx