One word answer: asynchronicity.
This topic has been iterated at least a couple of thousands of times here in Stack Overflow. Hence, first off I'd like to point out some extremely useful resources:
@Felix Kling's answer to "How do I return the response from an asynchronous call?". See his excellent answer explaining synchronous and asynchronous flows, as well as the "Restructure code" section.
@Benjamin Gruenbaum has also put a lot of effort into explaining asynchronicity in the same thread.
@Matt Esch's answer to "Get data from fs.readFile" also explains asynchronicity extremely well in a simple manner.
Let's trace the common behavior first. In all examples, theouterScopeVar
is modified inside of a function. That function is clearly not executed immediately; it is being assigned or passed as an argument. That is what we call a callback.
Now the question is, when is that callback called?
It depends on the case. Let's try to trace some common behavior again:
img.onload
may be called sometime in the future when (and if) the image has successfully loaded.setTimeout
may be called sometime in the future after the delay has expired and the timeout hasn't been canceled byclearTimeout
. Note: even when using0
as delay, all browsers have a minimum timeout delay cap (specified to be 4ms in the HTML5 spec).$.post
's callback may be called sometime in the future when (and if) the Ajax request has been completed successfully.fs.readFile
may be called sometime in the future when the file has been read successfully or thrown an error.In all cases, we have a callback that may run sometime in the future. This "sometime in the future" is what we refer to as asynchronous flow.
Asynchronous execution is pushed out of the synchronous flow. That is, the asynchronous code will never execute while the synchronous code stack is executing. This is the meaning of JavaScript being single-threaded.
More specifically, when the JS engine is idle -- not executing a stack of (a)synchronous code -- it will poll for events that may have triggered asynchronous callbacks (e.g. expired timeout, received network response) and execute them one after another. This is regarded as Event Loop.
That is, the asynchronous code highlighted in the hand-drawn red shapes may execute only after all the remaining synchronous code in their respective code blocks have executed:
In short, the callback functions are created synchronously but executed asynchronously. You can't rely on the execution of an asynchronous function until you know it has been executed, and how to do that?
It is simple, really. The logic that depends on the asynchronous function execution should be started/called from inside this asynchronous function. For example, moving thealert
s andconsole.log
s inside the callback function would output the expected result because the result is available at that point.
Often you need to do more things with the result from an asynchronous function or do different things with the result depending on where the asynchronous function has been called. Let's tackle a bit more complex example:
var outerScopeVar;
helloCatAsync();
alert(outerScopeVar);
function helloCatAsync() {
setTimeout(function() {
outerScopeVar = 'Nya';
}, Math.random() * 2000);
}
Note: I'm usingsetTimeout
with a random delay as a generic asynchronous function; the same example applies to Ajax,readFile
,onload
, and any other asynchronous flow.
This example clearly suffers from the same issue as the other examples; it is not waiting until the asynchronous function executes.
Let's tackle it by implementing a callback system of our own. First off, we get rid of that uglyouterScopeVar
which is completely useless in this case. Then we add a parameter that accepts a function argument, our callback. When the asynchronous operation finishes, we call this callback, passing the result. The implementation (please read the comments in order):
// 1. Call helloCatAsync passing a callback function,
// which will be called receiving the result from the async operation
helloCatAsync(function(result) {
// 5. Received the result from the async function,
// now do whatever you want with it:
alert(result);
});
// 2. The "callback" parameter is a reference to the function which
// was passed as an argument from the helloCatAsync call
function helloCatAsync(callback) {
// 3. Start async operation:
setTimeout(function() {
// 4. Finished async operation,
// call the callback, passing the result as an argument
callback('Nya');
}, Math.random() * 2000);
}
Code snippet of the above example:
// 1. Call helloCatAsync passing a callback function,
// which will be called receiving the result from the async operation
console.log("1. function called...")
helloCatAsync(function(result) {
// 5. Received the result from the async function,
// now do whatever you want with it:
console.log("5. result is: ", result);
});
// 2. The "callback" parameter is a reference to the function which
// was passed as an argument from the helloCatAsync call
function helloCatAsync(callback) {
console.log("2. callback here is the function passed as argument above...")
// 3. Start async operation:
setTimeout(function() {
console.log("3. start async operation...")
console.log("4. finished async operation, calling the callback, passing the result...")
// 4. Finished async operation,
// call the callback passing the result as argument
callback('Nya');
}, Math.random() * 2000);
}
Fabrício's answer is spot on; but I wanted to complement his answer with something less technical, which focusses on an analogy to help explain the concept of asynchronicity.
Yesterday, the work I was doing required some information from a colleague. I rang him up; here's how the conversation went:
Me: Hi Bob, I need to know how we foo'd the bar'd last week. Jim wants a report on it, and you're the only one who knows the details about it.
Bob: Sure thing, but it'll take me around 30 minutes?
Me: That's great Bob. Give me a ring back when you've got the information!
At this point, I hung up the phone. Since I needed information from Bob to complete my report, I left the report and went for a coffee instead, then I caught up on some email. 40 minutes later (Bob is slow), Bob called back and gave me the information I needed. At this point, I resumed my work with my report, as I had all the information I needed.
Imagine if the conversation had gone like this instead;
Me: Hi Bob, I need to know how we foo'd the bar'd last week. Jim want's a report on it, and you're the only one who knows the details about it.
Bob: Sure thing, but it'll take me around 30 minutes?
Me: That's great Bob. I'll wait.
And I sat there and waited. And waited. And waited. For 40 minutes. Doing nothing but waiting. Eventually, Bob gave me the information, we hung up, and I completed my report. But I'd lost 40 minutes of productivity.
This is exactly what is happening in all the examples in our question. Loading an image, loading a file off disk, and requesting a page via AJAX are all slow operations (in the context of modern computing).
Rather than waiting for these slow operations to complete, JavaScript lets you register a callback function which will be executed when the slow operation has completed. In the meantime, however, JavaScript will continue to execute other code. The fact that JavaScript executes other code whilst waiting for the slow operation to complete makes the behaviorasynchronous. Had JavaScript waited around for the operation to complete before executing any other code, this would have been synchronous behavior.
var outerScopeVar;
var img = document.createElement('img');
// Here we register the callback function.
img.onload = function() {
// Code within this function will be executed once the image has loaded.
outerScopeVar = this.width;
};
// But, while the image is loading, JavaScript continues executing, and
// processes the following lines of JavaScript.
img.src = 'lolcat.png';
alert(outerScopeVar);
In the code above, we're asking JavaScript to loadlolcat.png
, which is a sloooow operation. The callback function will be executed once this slow operation has done, but in the meantime, JavaScript will keep processing the next lines of code; i.e.alert(outerScopeVar)
.
This is why we see the alert showingundefined
; since thealert()
is processed immediately, rather than after the image has been loaded.
In order to fix our code, all we have to do is move thealert(outerScopeVar)
code into the callback function. As a consequence of this, we no longer need theouterScopeVar
variable declared as a global variable.
var img = document.createElement('img');
img.onload = function() {
var localScopeVar = this.width;
alert(localScopeVar);
};
img.src = 'lolcat.png';
You'll always see a callback is specified as a function, because that's the only* way in JavaScript to define some code, but not execute it until later.
Therefore, in all of our examples, thefunction() { /* Do something */ }
is the callback; to fix all the examples, all we have to do is move the code which needs the response of the operation into there!
* Technically you can useeval()
as well, but for this purpose
You might currently have some code similar to this;
function getWidthOfImage(src) {
var outerScopeVar;
var img = document.createElement('img');
img.onload = function() {
outerScopeVar = this.width;
};
img.src = src;
return outerScopeVar;
}
var width = getWidthOfImage('lolcat.png');
alert(width);
However, we now know that thereturn outerScopeVar
happens immediately; before theonload
callback function has updated the variable. This leads togetWidthOfImage()
returningundefined
, andundefined
being alerted.
To fix this, we need to allow the function callinggetWidthOfImage()
to register a callback, then move the alert'ing of the width to be within that callback;
function getWidthOfImage(src, cb) {
var img = document.createElement('img');
img.onload = function() {
cb(this.width);
};
img.src = src;
}
getWidthOfImage('lolcat.png', function (width) {
alert(width);
});
... as before, note that we've been able to remove the global variables (in this casewidth
).
Here's a more concise answer for people that are looking for a quick reference as well as some examples using promises and async/await.
Start with the naive approach (that doesn't work) for a function that calls an asynchronous method (in this casesetTimeout
) and returns a message:
function getMessage() {
var outerScopeVar;
setTimeout(function() {
outerScopeVar = 'Hello asynchronous world!';
}, 0);
return outerScopeVar;
}
console.log(getMessage());
undefined
gets logged in this case becausegetMessage
returns before thesetTimeout
callback is called and updatesouterScopeVar
.
The two main ways to solve it are using callbacks and promises:
Callbacks
The change here is thatgetMessage
accepts acallback
parameter that will be called to deliver the results back to the calling code once available.
function getMessage(callback) {
setTimeout(function() {
callback('Hello asynchronous world!');
}, 0);
}
getMessage(function(message) {
console.log(message);
});
Promises provide an alternative which is more flexible than callbacks because they can be naturally combined to coordinate multiple async operations. A Promises/A+ standard implementation is natively provided in node.js (0.12+) and many current browsers, but is also implemented in libraries like Bluebird and Q.
function getMessage() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve('Hello asynchronous world!');
}, 0);
});
}
getMessage().then(function(message) {
console.log(message);
});
jQuery Deferreds
jQuery provides functionality that's similar to promises with its Deferreds.
function getMessage() {
var deferred = $.Deferred();
setTimeout(function() {
deferred.resolve('Hello asynchronous world!');
}, 0);
return deferred.promise();
}
getMessage().done(function(message) {
console.log(message);
});
async/await
If your JavaScript environment includes support for and
(like Node.js 7.6+), then you can use promises synchronously within
async
functions:
function getMessage () {
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve('Hello asynchronous world!');
}, 0);
});
}
async function main() {
let message = await getMessage();
console.log(message);
}
main();
To state the obvious, the cup representsouterScopeVar
.
Asynchronous functions be like...
The other answers are excellent and I just want to provide a straight forward answer to this. Just limiting to jQuery asynchronous calls
All ajax calls (including the$.get
or$.post
or$.ajax
) are asynchronous.
Considering your example
var outerScopeVar; //line 1
$.post('loldog', function(response) { //line 2
outerScopeVar = response;
});
alert(outerScopeVar); //line 3
The code execution starts from line 1, declares the variable and triggers and asynchronous call on line 2, (i.e., the post request) and it continues its execution from line 3, without waiting for the post request to complete its execution.
Lets say that the post request takes 10 seconds to complete, the value ofouterScopeVar
will only be set after those 10 seconds.
To try out,
var outerScopeVar; //line 1
$.post('loldog', function(response) { //line 2, takes 10 seconds to complete
outerScopeVar = response;
});
alert("Lets wait for some time here! Waiting is fun"); //line 3
alert(outerScopeVar); //line 4
Now when you execute this, you would get an alert on line 3. Now wait for some time until you are sure the post request has returned some value. Then when you click OK, on the alert box, next alert would print the expected value, because you waited for it.
In real life scenario, the code becomes,
var outerScopeVar;
$.post('loldog', function(response) {
outerScopeVar = response;
alert(outerScopeVar);
});
All the code that depends on the asynchronous calls, is moved inside the asynchronous block, or by waiting on the asynchronous calls.
In all these scenariosouterScopeVar
is modified or assigned a value asynchronously or happening in a later time(waiting or listening for some event to occur),for which the current execution will not wait.So all these cases current execution flow results inouterScopeVar = undefined
Let's discuss each examples(I marked the portion which is called asynchronously or delayed for some events to occur):
1.
Here we register an eventlistner which will be executed upon that particular event.Here loading of image.Then the current execution continuous with next linesimg.src = 'lolcat.png';
andalert(outerScopeVar);
meanwhile the event may not occur. i.e, funtionimg.onload
wait for the referred image to load, asynchrously. This will happen all the folowing example- the event may differ.
2.
Here the timeout event plays the role, which will invoke the handler after the specified time. Here it is0
, but still it registers an asynchronous event it will be added to the last position of theEvent Queue
for execution, which makes the guaranteed delay.
3.
4.
Node can be consider as a king of asynchronous coding.Here the marked function is registered as a callback handler which will be executed after reading the specified file.
5.
Obvious promise (something will be done in future) is asynchronous. see What are the differences between Deferred, Promise and Future in JavaScript?
https://www.quora.com/Whats-the-difference-between-a-promise-and-a-callback-in-Javascript
The short answer is : asynchronicity.
Why asynchronous is needed?
JavaScript is single-threaded, meaning that two bits of the script cannot run at the same time; they have to run one after another. In browsers, JavaScript shares a thread with a load of other stuff that differs from browser to browser. But typically JavaScript is in the same queue as painting, updating styles, and handling user actions (such as highlighting text and interacting with form controls). Activity in one of these things delays the others.
You've probably used events and callbacks to get around this. Here are events:
var img1 = document.querySelector('.img-1');
img1.addEventListener('load', function() {
// image loaded
console.log("Loaded");
});
img1.addEventListener('error', function() {
// error caught
console.log("Error printed");
});
<img class="img-1" src="#" alt="img">
Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.
Find the answer in similar questions on our website.
Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.
PHP (from the English Hypertext Preprocessor - hypertext preprocessor) is a scripting programming language for developing web applications. Supported by most hosting providers, it is one of the most popular tools for creating dynamic websites.
The PHP scripting language has gained wide popularity due to its processing speed, simplicity, cross-platform, functionality and distribution of source codes under its own license.
https://www.php.net/
JavaScript is a multi-paradigm language that supports event-driven, functional, and mandatory (including object-oriented and prototype-based) programming types. Originally JavaScript was only used on the client side. JavaScript is now still used as a server-side programming language. To summarize, we can say that JavaScript is the language of the Internet.
https://www.javascript.com/
JQuery is arguably the most popular JavaScript library with so many features for modern development. JQuery is a fast and concise JavaScript library created by John Resig in 2006. It is a cross-platform JavaScript library designed to simplify client-side HTML scripting. Over 19 million websites are currently using jQuery! Companies like WordPress, Facebook, Google, IBM and many more rely on jQuery to provide a kind of web browsing experience.
https://jquery.com/
Node.js is an open source server-side framework built on top of the Google Chrome JavaScript Engine. The number of sites using NodeJS has increased by 84,000. It is one of the busiest cross-platform JavaScript runtimes. Node.js is an asynchronous, single-threaded, non-blocking I / O model that makes it lightweight and efficient. The Node.js package ecosystem, npm, is also the world's largest open source library ecosystem.
https://nodejs.org/
HTML (English "hyper text markup language" - hypertext markup language) is a special markup language that is used to create sites on the Internet.
Browsers understand html perfectly and can interpret it in an understandable way. In general, any page on the site is html-code, which the browser translates into a user-friendly form. By the way, the code of any page is available to everyone.
https://www.w3.org/html/
Welcome to the Q&A site for web developers. Here you can ask a question about the problem you are facing and get answers from other experts. We have created a user-friendly interface so that you can quickly and free of charge ask a question about a web programming problem. We also invite other experts to join our community and help other members who ask questions. In addition, you can use our search for questions with a solution.
Ask about the real problem you are facing. Describe in detail what you are doing and what you want to achieve.
Our goal is to create a strong community in which everyone will support each other. If you find a question and know the answer to it, help others with your knowledge.