This is a bit of a tricky concept to understand. Throwing in things like event listeners also further muddies up the picture.
A simple way to think of it is as if you have a conveyor belt. You have your normal function calls all evenly spaced out, with room in between.
Things that are asynchronous things (timeouts, triggered events, etc.) fill those spots. There isn't an infinite amount of room between each of those normal calls, so it fits what it can from this queue, does a little more of the normal synchronized functions, fills some more space with asynchronous, etc.
The affect appears to be somewhat multi-threaded (and indeed you can cause race conditions of a sort with asynchronous calls). In many cases, the distinction doesn't matter. However, it is important to remember this.
However, when you try to debug things, especially when using tools like Chrome's console.log
, it can look like things are scrambled because console.log itself is asynchronous (if it were synchronous, it would freeze your script on a long function).
You can see this yourself if you output something like this:
var input = document.createElement('input');
input.setAttribute('value', 0);
function inc() {
input.setAttribute('value', parseInt(input.getAttribute('value'))+1);
console.log(input);
if (parseInt(input.getAttribute('value')) < 100) {
setTimeout(inc, 10);
}
}
inc();
JSFiddle: http://jsfiddle.net/c2PnP/
What this script does it creates an input element, then every 10 milliseconds, it increments the value of input, then outputs the input element. It repeats 100 times (until value = 100).
If you look at your console, you'll notice that some of the values will be duplicated, it won't be a smooth progression. For example, on a run I just did, I see 5 inputs with a value of "100" and gaps for the missing numbers. This is because console.log is running asynchronously and only outputting when it gets the gap to do so.
(Note: If you have a super fast computer, you may need to decrease the time to something smaller, like 1, and/or increase the number of iterations to a bigger number).
console.log
is asynchronous, at least across IE, Firefox, Chrome. More: #4057940. Asynchrony doesn't assume multi-threading. – Kora