Callbacks in JavaScript do not implicitly add asynchronous behavior. When a callback function is invoked, it runs right then, just as a normal function. (Actually, a callback function is just a normal function...)
Because of this, it is impossible to determine when the execution of the callback in the example will run in relationship to the other methods (except that it can't run before methodA
is invoked) -- it could be called from methodA
or methodB
or from a click later, or not at all. (However, unless there is an exception -- or one of the functions invokes one of the other functions -- then methodA
will run before methodB
which will in turn run before methodC
; if methodA
threw an exception then neither methodB
nor methodC
would be invoked).
What does add asynchronous behavior is an asynchronous event source, such as a timer event or UI action such as a button click.
However, it is important to keep in mind that Javascript does not have or support threading. The Javascript must "stop" (execution must return from the callback function invoked from an asynchronous event source) before a new asynchronous event can be triggered. (Asynchronous events are queued [as appropriate] so a timer event won't be "lost" if another callback takes too long to execute.)
This is why while (true) {}
will make a browser page freeze and prevent button event handlers from being processed.
Happy coding.
Example cases (jsfiddle demo):
function invokeNow(callback) {
// nothing asynchronous going on here.
// the callback is invoked right now and the result is returned.
return callback()
}
alert(invokeNow(function () { return "Hello world!" }))
function doLater(callback) {
// setup an asynchronous event
setTimeout(callback, 1000)
return "It isn't 'later' yet!"
}
alert(doLater(function () {
alert("Later!")
// note that this is running in the callback from the previous
// timer event. if this code was below the outer alert then
// it wouldn't have allowed the first timer callback to have occurred
// until the blocking while was complete
alert(doLater(function () { alert("I still ran!") }))
var end = (+new Date) + 4000
while ((+new Date) < end) { /* wait */ }
alert("I am done waiting")
}))
Warning: There seems to be an issue with Firefox 4 (4.0.1) and the code above. While it works as demonstrated, the expected order differs from the actual order if the timeout is below about 800ms. I have posted SO: Asynchronous timer event running synchronously (“buggy”) in Firefox 4? so hopefully there will be some resolution. The behavior works as expected in Firefox 3, IE 9, and Chrome 11.