This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What does Asynchronous means in Ajax?
jQuery ajax return value
Trying to do a function that contains a jQuery function (getJson()) as part of it, but when I run it, my javascript function returns before calling the getJson(). I want to know why the getJson is not being called in order, and how to fix it.
function getUsers(screen_name){
user_list=[]
var id_list =[]
$.getJSON(url, function(json)
{
//do stuff here, I have breakpoint #1 here
});
return user_list //breakpoint #2 is here
}
When running it from the console: getUsers('myUser') it firsts gets to breakpoint #2 and then to breakpoint #1.
getJSON() is asynchronous by default. That means that calling it just starts the operation and the rest of your javascript continues to run. Sometime later, the asynchronous operation finishes and the success handler is called with the returned data.
Any code that needs access to the returned data must either be in the success handler or in a function that you call from the success handler. You cannot use an asynchronous function and just return the user_list like you are trying to.
Instead, you will have to rethink how your code is organized so that the code that uses the user_list is in the success handler or is called from the success handler.
getJSON() can be set to be synchronous, but that is generally a bad way to program in javascript because it locks up the browser for the duration of the networking call which is generally a bad user experience. Instead, if you write the code properly to deal with it being aschronous, then the browsers stays completely interactive for the full duration of the ajax call.
Related
I've seen quite a few questions about exection order issues in JavaScript involving ajax calls.
If there are no ajax calls, is it safe to assume that code will execute from top to bottom?
Say, I have this code below. None of the functions that I'm calling have any async calls in them.
someFunction() {
// Call some external function
doSomething();
// Then call another external function
const x = doSomethingElse();
if(x === 0) {
// Call third function
thirdFunction();
}
}
Currently, I'm running into a situation where it appears as if doSomething() is not getting called first. Is this possible?
P.S. I'm having this issue in a React/Redux app and doSomething() is an action that is supposed to reset/clear something in the store but currently that's not working.
Along with ajax calls promises that don't resolve (for example event listeners waiting for an event that never happens) and timeout code that gets pushed to next event cycle are also async.
If doSomething() has any one of these then it might not get executed.
Yes. If you don't have any function which has asynchronous calls like AJAX, execution order is always the same as it is.
I'm completely new in javascript and I'm trying to understand its asynch nature. For this purpose here is my sample code :
$("#calculate-similarity").click(function(){
// assume input is an array whose length is larger than 0
var requestData={"uris":input,"limit":100};
client=new Ajax(requestData);
alert('inside .click function');
})
Ajax=function(requestData){
alert('inside ajax');
$.ajax({
url: 'http://localhost:8080/',
type:'POST',
dataType: 'json',
contentType: 'application/json',
data: JSON.stringify(requestData),
xhrFields: {
withCredentials: true
}
}).done(function(data) {
$("#ws-results").children().detach();
$("#ws-results").append('<table id="my-final-table"><thead><th>fname</th><th>furi</th><th>sname</th><th>suri</th><th>similarity</th></thead><tbody></tbody></table>');
$('#my-final-table').dynatable({
dataset: {
records:data
}
});
});
}
Now, above, I'm creating new Ajax() and inside of it, I'm making a ajax request. As far as I know its asynch event. Therefore, I though that, this request should be completed first of all, and then my other javascript lines (alert('inside .click function')) should be executed. In other words, I would expect :
1) alert inside ajax
2) show my datatable on the browser
3) alert inside .click function
However, I got with the following order :
1) alert inside ajax
2) alert inside .click function
3) show table on the browser
So, what do you suggest me to understand these concepts ? I've a solid background with several programming languages like c++ and java but this is my first time with web development and javascript.
EDIT
If I modify my .click function like below, do you say first of all always 10000 times hello will be printed out and then table will be shown ? Or table would be shown somewhere at the middle of logging ? I mean when the response comes, engine should wait first in order to show it ?
Modified code : (Let's remove all of the alert statements)
$("#calculate-similarity").click(function(){
// assume input is an array whose length is larger than 0
var requestData={"uris":input,"limit":100};
client=new Ajax(requestData);
for(var z=0;z<10000;z++){
console.log(z+'hi!');
}
})
As far as I know its asynch event. Therefore, I though that, this request should be completed first of all, and then my other javascript lines should be executed.
That is exactly the opposite of what it means.
The Ajax function will run. It will trigger an HTTP request. The Ajax function will finish. alert will run.
At some point in the future, the HTTP response will arrive and the done event handler will fire.
This is exactly the same principle as:
alert(1);
$("#calculate-similarity").click(function(){ alert(2); });
alert(3);
JavaScript doesn't wait for you to click on calculate-similarity before firing alert(3).
If I modify my .click function like below, do you say first of all always 10000 times hello will be printed out and then table will be shown ? Or table would be shown somewhere at the middle of logging ? I mean when the response comes, engine should wait first in order to show it ?
JavaScript won't interrupt a running function in order to execute a different (event handler) function. It will wait until it isn't busy before it goes looking for events.
new Ajax is object instantiation and it's synchronous. Therefore you get inside ajax as the first result because it happens when your Ajax object is instantiated, not to be confused with when the Ajax request is fired.
alert is executed synchronously, so that's the second thing you get.
$.ajax which wraps around XMLHttpRequest, responsible for firing the actual ajax request, is the only async part in your code and its result, which is encapsulated inside done, is what you get last.
In other words, I think the confusion comes from the fact that you introduce another layer of abstraction called new Ajax() which provide little actual value and a lot of confusion :P. inside ajax signal inside the instantiation of your Ajax object, not the firing of the actual request.
I'll try my best to explain it. Think of this more as an analogy, it's not exactly what's going on but I think it might help you understand:
alert('inside ajax'); - this is a blocking call, it will run and wait for you to click OK.
Then when you call Ajax, what you're essentially doing is saying "go make this web request when you have a chance, and when it finishes call my done method." That's a network operation. It could finish in 1 second, it could take many seconds. Rather than freezing up the whole browser, this is done "in the background." So that makes the UI remains responsive. At some point in the future the network request will finish. When it does, the function you specified in done will get called to let you know it finished. Think of making the Ajax request as adding it to a queue rather than actually connecting to the network. When the browser gets to it it will execute your request and wait for the server to respond. When it does, it will signal you to let you know.
Next you alert('inside .click function'); which displays the alert and blocks.
Like I said, that's not a technically accurate description of what's going on, but I'm hoping it helps you understand the principle of it.
I am new to JavaScript and I have a question regarding asynchronous functions when I read about it in the book "JavaScript the good parts":
I understand that the following code will be executed synchronously and may cause delay:
request = prepare_the_request();
response = send_request_synchronously(request);
display(response);
However, the following code is said to be executed asynchronously:
request = prepare_the_request();
send_request_asynchronously(request, function(response){
display(response);
});
How does the compiler(or interpreter? I am not sure how JavaScript is interpreted) know that the second block of code is supposed to be executed asynchronously?
Thank you in advance.
(If the question is not clear please comment and I am sorry for not expressing it clearly.)
Compiler/Interpreter doesn't know that, and actually doesn't care about it. On multiprocess operating systems, two or more threads can run concurrently, and Javascript's XMLHTTPRequest object allows to run the request in a separate thread. This way, Javscript starts the thread, but since it is running in a separate thread, it doesn't wait and continue with next command.
I'll be completely honest... the first time I read that same Callbacks section on page 53 of Javascript, the good parts, I also made the same assumption as you did hahaha, though only later did I find out what the author meant.
Your previous statement isn't actually correct:
However, the following code is said to be executed asynchronously:
Before the Author displays the code with the callback function, he says the following paragraph:
A better approach is to make an asynchronous request, providing a
callback function that will be invoked when the server’s response is
received. An asynchronous function returns immediately, so the client
isn’t blocked:
The important part here is: ...make an asynchronous request, PROVIDING a callback function...
The author was trying to make the point that you could make a function like:
send_request_asynchronously(request, function (response) {
display(response);
});
that doesn't execute function (response) {display(response);} at the time the code is run through the interpreter, but rather some time in the future when a call to send_request_asynchronously is made AND later on in the code you could make it asynchronous. The very code itself has nothing asynchronous about it. It's designed to be called asynchronously later.
The "PROVIDING a callback function" is key to infering this is what the author meant. If you notice, there is no trailing () after the callback function. If you did have a trailing () like so:
send_request_asynchronously(request, function (response) {
display(response);
}());//<--- right here
then the function would execute right then and there when the interpreter was reading through that portion of the code, hence forcing the system to be Synchronous, where as by not including (), you open the door for it to be Asynchronous in the future by implementing code with Asynchronous features that then call this function.
As a final important point, lets remember that this is what makes a callback function a callback function. It is not being invoked when you include the function in the parameter. So for instance, if I make a function called salutations:
var salutations = function (hello(){alert('hi')})
{
alert ('salutations!');
}
and if I had no more code after the previous code, you would never see an alert popup. It would only be invoked when called/invoked after it's declaration/iniciation (HENCE the term: "it's being called back" after it was created AKA callback). However, if I included a trailing () after the callback function, it would then cause the function to actually execute during the declaration and initiation of function salutations.
Based on chrome developer tools a breakpoints I think I'm dealing with a scope issue I can figure out. Is it the way I define the function? The script below is an include js file and the array ' timeStamp I want available for use in other functions without having to call my loadData function everytime.
The timeStamp array goes undefined once it leaves the for loop before it even leaves the function.
var timeStamp = []; // Want this array to be global
function loadData (url){
$.getJSON(url, function(json) {
for (var i=0;i<json.length;i++){
timeStamp.push(json[i].TimeStamp);
}
console.log(inputBITS); //returns the value
});
console.log(inputBITS); //undefined
}
Thank you for anyhelp
It looks like the issue is that getJSON is asynchronous. When it executes and finishes and your code continues on, it indicates only the START of the networking operation to retrieve the data. The actual networking operation does not complete until some time later.
When it does complete, the success handler is called (as specified as the second argument to your getJSON() call) and you populate the timeStamp array. ONLY after that success handler has been called is the timeStamp array valid.
As such, you cannot use the timeStamp array in code that immediately follows the getJSON() call (it hasn't been filled in yet). If other code needs the timeStamp array, you should call that code from the success handler or use some other timing mechanism to make sure that the code that uses the timeStamp array doesn't try to use it until AFTER the success handler has been called and the timeStamp array has been populated.
It is possible to make some Ajax calls be synchronous instead of asynchronous, but that is generally a very bad idea because it locks up the browser during the entire networking operation which is very unfriendly to the viewer. It is much better to fix the coding logic to work with asynchronous networking.
A typical design pattern for an ajax call like this is as follows:
function loadData (url){
$.getJSON(url, function(json) {
// this will execute AFTER the ajax networking finishes
var timeStamp = [];
for (var i=0;i<json.length;i++) {
timeStamp.push(json[i].TimeStamp);
}
console.log(timeStamp);
// now call other functions that need timeStamp data
myOtherFunc(timeStamp);
});
// this will execute when the ajax networking has just been started
//
// timeStamp data is NOT valid here because
// the ajax call has not yet completed
// You can only use the ajax data inside the success handler function
// or in any functions that you call from there
}
And here's another person who doesn't understand basic AJAX...
getJSON is asynchronous. Meaning, code keeps running after the function call and before the successful return of the JSON request.
You can "fix" this by forcing the request to be synchronous with an appropriate flag, but that's a really bad idea for many reasons (the least of which is that you're violating the basic idea of AJAX). The best way is to remember how AJAX works and instead put all your code that should be executed when the AJAX returns, in the right place.
To speed up my application I want to prepare some data before DOM is ready and then use this data when DOM is ready.
Here's how it might be:
var data = function prepareData(){
...
}();
$(document).ready(function() {
// use data to build page
}
How to prepare the data for later use?
Thanks
You need should use parentheses around the function expression for clarity (and because in a similar situation where you're defining and calling a function but not using the return value, it would be a syntax error without them). Also, when you use a function expression, you want to not give it a name. So:
var data = (function(){
...
})();
or use a function declaration instead:
var data = processData();
function processData() {
...
}
(Why not use a name with a function expression? Because of bugs in various implementations, especially Internet Explorer prior to IE9, which will create two completely unrelated functions.)
However, it's not clear to me what you're trying to achieve. When the browser reaches the script element, it hands off to the JavaScript interpreter and waits for it to finish before continuing building the DOM (because your script might use document.write to add to the HTML token stream). You can use the async or defer attributes to promise the browser you're not going to use document.write, on browsers that support them, but...
Update: Below you've said:
because prepareData is long time function and I assumed that browser can execute this while it's building DOM tree. Unfortunately '$(document).ready' fires before prepareData is finished. The question is how to teach '$(document).ready' to wait for ready data
The only way the ready handler can possibly trigger while processData is running is if processData is using asynchronous ajax (or a couple of edge conditions around alert, confirm, and the like, but I assume you're not doing that). And if it were, you couldn't be returning the result as a return value from the function (though you could return an object that you continued to update as the result of ajax callbacks). Otherwise, it's impossible: JavaScript on browsers is single-threaded, the ready handler will queue waiting for the interpreter to finish its previous task (processData).
If processData isn't doing anything asynchronous, I suspect whatever the symptom is that you're seeing making you think the ready handler is firing during processData has a different cause.
But in the case of asynchronous stuff, three options:
If you're not in control of the ready handlers you want to hold up, you might look at jQuery's holdReady feature. Call $.holdReady(true); to hold up the event, and use $.holdReady(false); to stop holding it up.
It's simple enough to reschedule the ready handler. Here's how I'd do it (note that I've wrapped everything in a scoping function so these things aren't globals):
(function() {
var data = processData();
$(onPageReady);
function processData() {
}
function onPageReady() {
if (!data.ready) {
// Wait for it to be ready
setTimeout(onPageReady, 0); // 0 = As soon as possible, you may want a
// longer delay depending on what `processData`
// is waiting for
return;
}
}
})();
Note that I happily use data in the onPageReady function, because I know that it's there; that function will not run until processData has returned. But I'm assuming processData is returning an object that is slowly being filled in via ajax calls, so I've used a ready flag on the object that will get set when all the data is ready.
If you can change processData, there's a better solution: Have processData trigger the ready handler when it's done. Here's the code for when processData is done with what it needs to do:
$(onPageReady);
That works because if the DOM isn't ready yet, that just schedules the call. If the DOM is already ready, jQuery will call your function immediately. This prevents the messy looping above.