Continuation-Passing Style And Concurrency - javascript

I find lots of blogs mention concurrent/non-blocking/asynchronous programming as a benefit of Continuation-Passing Style (CPS). I cannot figure out why CPS provides concurrency, e.g., people mention Node.js is implemented using CPS though JavaScript is a synchronous language. Would someone comment on my thoughts?
First, my naive understanding of CPS is that wrapping all subsequent code at a point into a function and pass that function explicitly as a parameter. Some blogs name the continuation function as return(), Gabriel Gonzalez calls it a hole, both of which are brilliant explanations.
My confusion mostly comes from a popular blog article Asynchronous programming and continuation-passing style in JavaScript. At the beginning of the article, Dr. Axel Rauschmayer gives two code snippets, a synchronous program and an asynchronous one in CPS (pasted here for easy reading).
The synchronous code:
function loadAvatarImage(id) {
var profile = loadProfile(id);
return loadImage(profile.avatarUrl);
}
The asynchronous code:
function loadAvatarImage(id, callback) {
loadProfile(id, function (profile) {
loadImage(profile.avatarUrl, callback);
});
}
I don't get it why the CPS one is asynchronous. After I read another article By example: Continuation-passing style in JavaScript, I think maybe there is an assumption to the code: the function loadProfile() and loadImage() are asynchronous functions by themselves. Then it is not CPS that makes it asynchronous. In the second article, the author actually shows an implementation of fetch(), which is similar to loadProfile() in the blog earlier. The fetch() function makes an explicit assumption of the underlying concurrent execution model by calling req.onreadystatechange. This leads me to think maybe it is not CPS that provides concurrency.
Assume the underlying functions are asynchronous, then I go into my second question: can we write asynchronous code without CPS? Think of the implementation of the function loadProfile(). If it is asynchronous not because of CPS, why can't we just take the same mechanism to implement loadAvatarImage() asynchronously? Assume loadProfile() uses fork() to create a new thread to send the request and wait for the response while the main thread is executing in a non-blocking manner, we can possibly do the same for loadAvatarImage().
function loadAvatarImage(id, updateDOM) {
function act () {
var profile = loadProfile(id);
var img = loadImage(profile.avatarUrl);
updateDOM (img);
}
fork (act());
}
I give it a callback function updateDOM(). Without updateDOM(), it is not fair to compare it with the CPS version -- the CPS version has extra information about what to do after the image is fetched, i.e., the callback function, but the original synchronous loadAvatarImage() does not.
Interestingly, #DarthFennec pointed out my new loadAvatarImage() is actually CPS: fork() is CPS, act() is CPS (if we explicitly give it updateDOM), and loadAvatarImage() is CPS. The chain makes loadAvatarImage() asynchronous. loadProfile() and loadImage() do not need to be asynchronous or CPS.
If the reasoning up to here is correct, can I get these two conclusions?
Given a set of synchronous APIs, someone coding following CPS will not magically create asynchronous functions.
If the underlying asynchronous/concurrent APIs are provided in the CPS style, like CPS versions of loadProfile(), loadImage(), fetch(), or fork(), then one can only code in CPS style to ensure the asynchronous APIs are used asynchronously, e.g., return loadImage(profile.avatarUrl) will nullify the concurrency of loadImage().

A Brief Overview of Javascript
Javascript's concurrency model is non-parallel and cooperative:
Javascript is non-parallel because it runs in a single thread; it achieves concurrency by interleaving multiple execution threads, rather than by actually running them at the same time.
Javascript is cooperative because the scheduler only switches to a different thread when the current thread asks it to. The alternative would be preemptive scheduling, where the scheduler decides to arbitrarily switch threads whenever it feels like it.
By doing these two things, Javascript avoids many problems that other languages don't. Parallel code, and non-parallel preemptively-scheduled code, cannot make the basic assumption that variables will not suddenly change their values in the middle of execution, since another thread might be working on the same variable at the same time, or the scheduler might decide to interleave another thread absolutely anywhere. This leads to mutual exclusion problems and confusing race condition bugs. Javascript avoids all of this because in a cooperatively-scheduled system, the programmer decides where all the interleaves happen. The main drawback of this is if the programmer decides not to create interleaves for long periods of time, other threads never have a chance to run. In a browser, even actions like polling for user input and drawing updates to the page run in the same single-threaded environment as the Javascript, so a long-running Javascript thread will cause the entire page to become unresponsive.
In the beginning, CPS was most often used in Javascript for the purpose of event-driven UI programming: if you wanted some code to run every time someone pressed a button, you would register your callback function to the button's 'click' event; when the button was clicked, the callback would run. As it turns out, this same approach could be used for other purposes as well. Say you want to wait one minute and then do a thing. The naive approach would be to stall the Javascript thread for sixty seconds, which (as stated above) would cause the page to crash for that duration. However, if the timer was exposed as a UI event, the thread could be suspended by the scheduler instead, allowing other threads to run in the meantime. Then, the timer would cause the callback to execute, in the same way a button press would. The same approach can be used to request a resource from the server, or to wait for the page to load fully, or a number of other things. The idea is that, to keep Javascript as responsive as possible, any built-in function that might take a long time to complete should be part of the event system; in other words, it should use CPS to enable concurrency.
Most languages that support cooperative scheduling (often in the form of coroutines) have special keywords and syntax that must be used to tell the language to interleave. For example, Python has the yield keyword, C# has async and await, etc. When Javascript was first designed, it had no such syntax. It did, however, have support for closures, which is a really easy way to allow CPS. I expect the intention behind this was to support the event-driven UI system, and that it was never intended to become a general-purpose concurrency model (especially once Node.js came along and removed the UI aspect entirely). I don't know for sure, though.
Why does CPS provide concurrency?
To be clear, continuation-passing style is a method that can be used to enable concurrency. Not all CPS code is concurrent. CPS isn't the only way to create concurrent code. CPS is useful for things other than enabling concurrency. Simply put, CPS does not necessarily imply concurrency, and vice versa.
In order to interleave threads, execution must be interrupted in such a way that it can be resumed later. This means the context of the thread must be preserved, and later re-instated. This context isn't generally accessible from inside of a program. Because of this, the only way to support concurrency (short of the language having special syntax for it) is to write the code in such a way that the thread context is encoded as a value. This is what CPS does: the context to be resumed is encoded as a function that can be called. This function being called is equivalent to a thread being resumed. This can happen any time: after an image is loaded, after a timer triggers, after other threads have had a chance to run for a while, or even immediately. Since the context is all encoded into the continuation closure, it doesn't matter, as long as it runs eventually.
To better understand this, we can write a simple scheduler:
var _threadqueue = []
function fork(cb) {
_threadqueue.push(cb)
}
function run(t) {
_threadqueue.push(t)
while (_threadqueue.length > 0) {
var next = _threadqueue.shift()
next()
}
}
An example of this in use:
run(function() {
fork(function() {
console.print("thread 1, first line")
fork(function() {
console.print("thread 1, second line")
})
})
fork(function() {
console.print("thread 2, first line")
fork(function() {
console.print("thread 2, second line")
})
})
})
This should print the following to the console:
thread 1, first line
thread 2, first line
thread 1, second line
thread 2, second line
The results are interleaved. While not particularly useful on its own, this logic is more or less the foundation of something like Javascript's concurrency system.
Can we write asynchronous code without CPS?
Only if you have access to the context through some other means. As previously stated, many languages do this through special keywords or other syntax. Some languages have special builtins: Scheme has the call/cc builtin, which will wrap the current context into a callable function-like object, and pass that object to its argument. Operating systems get concurrency by literally copying around the thread's callstack (the callstack contains all of the needed context to resume the thread).
If you mean in Javascript specifically, then I'm fairly certain it's impossible to reasonably write asynchronous code without CPS. Or it would be, but newer versions of Javascript also come with the async and await keywords, as well as a yield keyword, so using those is becoming an option.
Conclusion: Given a set of synchronous APIs, someone coding following CPS will not magically create asynchronous functions.
Correct. If an API is synchronous, CPS alone will not make that API asynchronous. It may introduce a level of concurrency (as in the example code earlier), but that concurrency can only exist within the thread. Asynchronous loading in Javascript works because the loading itself runs in parallel to the scheduler, so the only way to make a synchronous API asynchronous is to run it in a separate system thread (which can't be done in Javascript). But even if you did do that, it still wouldn't be asynchronous unless you also used CPS.
CPS doesn't cause asynchronicity. However, asynchronicity does require CPS, or some alternative to CPS.
Conclusion: If the underlying asynchronous/concurrent APIs are provided in the CPS style, then one can only code in CPS style
Correct. If the API is loadImage(url, callback) and you run return loadImage(profile.avatarUrl), it will return null immediately and it will not give you the image. Most likely it will throw an error because callback is undefined, since you didn't pass it. Essentially, if the API is CPS and you decide not to use CPS, you're not using the API correctly.
In general though, it is accurate to say that if you write a function that calls a CPS function, your function also needs to be CPS. This is actually a good thing. Remember what I said about the basic assumption that variables will not suddenly change their values in the middle of execution? CPS solves this issue by making it very clear to the programmer where exactly the interleave boundaries are; or rather, where values might arbitrarily change. But if you could hide CPS function calls inside of non-CPS functions, you would no longer be able to tell. This is also the reason the newer Javascript async and await keywords work the way they do: any function that uses await must be marked as async, and any call to an async function must be prefixed with the await keyword (there's more to it than that, but I don't want to get into how promises work just now). Because of this, you can always tell where your interleave boundaries are, because there will always be await keywords there.

Related

JavaScript is synchronous then why we need callback function

since javascript is synchronous then why do we need callback function,
in the below picture both code can same thing
As #Meno-101 rightly said, you're looking at the trivial function invocation utility of callbacks, they're rather used for asynchronous calls. In asynchronous calls we wait for some data to arrive and then invoke a function, you won't see a difference when you're being presented with the result in an instant. setTimeout is one easy way to replicate such a situation;
Callbacks are generally used when the function needs to perform events before the callback is executed, or when the function does not (or cannot) have meaningful return values to act on, as is the case for Asynchronous JavaScript (based on timers) or XMLHttpRequest requests. Checkout the deets here
But if we're are bent on using it synchronously , I could only come up with this code:
This made the code reusable which isn't possible the other way, we'd have to write different definitions of same function for disp() and disp1() to function.
You’re just confusing callback’s purpose with a function invocation purpose.
Callbacks are used in the case of web requests, reading/writing to files, or maybe even just waiting for some reason the programmer only know why, take this example:
setTimeout(()=> console.log(“hello”), 3000)
There must be a reason for you to have this in your code, what ever it’s you don’t want all the page to hang up on the user.
And, I do recommend you look for function call stack if you’re just starting off.

What makes a JavaScript function asynchronous?

I am aiming to understand what exactly is it about certain JavaScript functions that make them asynchronous. You could have a function like this:
function someRandomFunction () {
for (let i of everything) {
iterator++
something = true
hello = that + whatever
}
}
Nothing about this function is asynchronous. It does a lot of stuff but it does it very quickly.
But then take a Node.js function like this:
fs.readFile('path/to/file', (err, data) => {
// do something
})
This function is declared to be asynchronous. But why is it? What is the reason behind it?
Is it because it takes a certain amount of time for reading a file to complete, therefore it's asynchronous? Why is that asynchronous when looping through some variables and doing some calculations is not asynchronous?
The 'idea' of something being asynchronous means "we've relinquished control to some other operational code, and we have no idea when that other code will allow us to operate again".
So in your bottom sample, you give control over to node's filesystem operations to read a file. We don't know how large that file is, so there is no way to anticipate how much time it will take to complete. So JavaScript allows us to provide a "callback" that get's fired when the async operation is complete. When the callback is executed, control is returned to our code.
The top example is synchronous because your code maintains control over the operation and Javascript executes code synchronously by nature.
A function is either explicitly synchronous or asynchronous; there's no "certain amount of time" that automatically makes it asynchronous.
The important thing to remember with Node is that it's "async I/O", which means nothing is ever async without some input/output to/from the process. You normally see this with file reading/writing, database calls, and anything that requires a network call.
This is a basic but fundamental question. Passing a function to another function doesn't make the code asynchronous automatically. It's all about attemting to work with another piece of code, mostly of unknown origins, probably but not necessarily related with operating system's IO mechanism. In another words you ask something to happen out of the realm of the currently exectuing JS context by handing a task to known or unknown resources which are possibly running on a separate thread.
As i said this can be an IO operation or a database access of which you have no idea on
What code is running
At which thread it is running
How long it will take
Whether it will succeed or not
Behind the curtains these alien codes finally trigger the event queue to invoke the callback function through a driver. In some pure functional languages like Haskell such activities are strictly kept away from the context and must be handled by monadic type functions. In JS this is basically done by asynchronous workflow by callbacks, promises or async-awiat mechanism.
Once you hand out a task to the outer world then there shall be no way for it to interfere with your synchronous code.
In terms of JavaScript, the difference between synchronous and async functions is where and when the code is executed. Synchronous functions are executed immediately one after the other in the current call stack. Async functions are passed off to the event loop, and values returned once the current call stack has completed execution.
Caveat being, nothing in JavaScript is truly asynchronous due to the fact that JS only executes on a single process thread

What do we call JS async "strands of execution"?

In Java we have "threads", in CPython we have threads (non-concurrent) and "processes".
In JS, when I kick off an async function or method, how do I officially refer to these "strands of executing code"?
I have heard that each such code block executes from start to finish*, meaning that there is never any concurrent** processing in JS. I'm not quite sure whether this is the same situation as with CPython threads. Personally I hesitate to use "thread" for what we have in JS as these "strands" are so different from Java concurrent threads.
* Just to clarify in light of Stephen Cleary's helpful response: I mean "each such synchronous code block". Obviously if an await is encountered control is released ...
** And obviously never any "true parallel" processing. I'm following the widely accepted distinction between "concurrent" (only one thread at any one time, but one "strand of execution" may give way to another) and "parallel" (multiple processes, implementing true parallel processing, often using multiple CPUs or cores or processes). My understanding is that these "strands" in JS are not even concurrent: once one AJAX method or Promise or async method/function starts executing nothing can happen until it's finished (or an await happens)...
In JS, when I kick off an async function or method, how do I officially refer to these "strands of executing code"?
For lack of a better term, I've referred to these as "asynchronous operations".
I have heard that each such code block executes from start to finish
This was true... until await. Now there's a couple of ways to think about it, both of which are correct:
Code blocks execute exclusively unless there's an await.
await splits its function into multiple code blocks that do execute exclusively (each await is a "split point").
meaning that there is never any concurrent processing in JS.
I'd disagree with this statement. JavaScript forces asynchrony (before async/await, it used callbacks or promises), so it does have asynchronous concurrency, though not parallel concurrency.
A good mental model is that JavaScript is inherently single-threaded, and that one thread has a queue of work to do. await does not block that thread; it returns, and when its thenable/Promise completes, it schedules the remainder of that method (the "continuation") to the queue.
So you can have multiple asynchronous methods executing concurrently. This is exactly how Node.js handles multiple simultaneous requests.
My understanding is that these "strands" in JS are not even concurrent: once one AJAX method or Promise or async method/function starts executing nothing can happen until it's finished...
No, this is incorrect. await will return control to the main thread, freeing it up to do other work.
the way things operate in JS means you "never have to worry about concurrency issues, etc."
Well... yes and no. Since JavaScript is inherently single-threaded, there's never any contention over data shared between multiple threads (obviously). I'd say that's what the original writer was thinking about. So I'd say easily north of 90% of thread-synchronization problems do just go away.
However, as you noted, you still need to be careful modifying shared state from multiple asynchronous operations. If they're running concurrently, then they can complete in any order, and your logic has to properly handle that.
Ideally, the best solution is to move to a more functional mindset - that is, get rid of the shared state as much as possible. Asynchronous operations should return their results instead of updating shared state. Then these concurrent asynchronous operations can be composed into a higher-level asynchronous operation using async, await, and Promise.all. If possible, this more functional approach of returning-instead-of-state and function composition will make the code easier to deal with.
But there's still some situations where this isn't easily achievable. It's possible to develop asynchronous equivalents of classical synchronous coordination primitives. I worked up a proof-of-concept AsyncLock, but can't seem to find the code anywhere. Well, it's possible to do this, anyway.
To date 24 people, no more no fewer, have chosen to look at this.
FWIW, and should anyone eccentric take an interest in this question one day, I propose "hogging strands" or just "strands" ... they hog the browser's JS engine, it would appear, and just don't let go, unless they encounter an await.
I've been developing this app where 3 "strands" operate more or less simultaneously, all involving AJAX calls and a database query... but in fact it is highly preferable if the 2nd of the 3 executes and returns before the 3rd.
But because the 3rd query is quite a bit simpler for MySQL than the 2nd the former tends to return from its AJAX "excursion" quite a bit earlier if everything is allowed to operate with unconstrained asynchronicity. This then causes a big delay before the 2nd strand is allowed to do its stuff. To force the code to perform and complete the 2nd "strand" therefore requires quite a bit of coercion, using async and await.
I read one comment on JS asynchronicity somewhere where someone opined that the way things operate in JS means you "never have to worry about concurrency issues, etc.". I don't agree: if you don't in fact know when awaits will unblock this does necessarily mean that concurrency is involved. Perhaps "hogging strands" are easier to deal with than true "concurrency", let alone true "parallelism", however... ?

I know that callback function runs asynchronously, but why?

Which part of syntax provides the information that this function should run in other thread and be non-blocking?
Let's consider simple asynchronous I/O in node.js
var fs = require('fs');
var path = process.argv[2];
fs.readFile(path, 'utf8', function(err,data) {
var lines = data.split('\n');
console.log(lines.length-1);
});
What exactly makes the trick that it happens in background? Could anyone explain it precisely or paste a link to some good resource? Everywhere I looked there is plenty of info about what callback is, but nobody explains why it actually works like that.
This is not the specific question about node.js, it's about general concept of callback in each programming language.
EDIT:
Probably the example I provided is not best here. So let's do not consider this node.js code snippet. I'm asking generally - what makes the trick that program keeps executing when encounter callback function. What is in syntax
that makes callback concept a non-blocking one?
Thanks in advance!
There is nothing in the syntax that tells you your callback is executed asynchronously. Callbacks can be asynchronous, such as:
setTimeout(function(){
console.log("this is async");
}, 100);
or it can be synchronous, such as:
an_array.forEach(function(x){
console.log("this is sync");
});
So, how can you know if a function will invoke the callback synchronously or asynchronously? The only reliable way is to read the documentation.
You can also write a test to find out if documentation is not available:
var t = "this is async";
some_function(function(){
t = "this is sync";
});
console.log(t);
How asynchronous code work
Javascript, per se, doesn't have any feature to make functions asynchronous. If you want to write an asynchronous function you have two options:
Use another asynchronous function such as setTimeout or web workers to execute your logic.
Write it in C.
As for how the C coded functions (such as setTimeout) implement asynchronous execution? It all has to do with the event loop (or mostly).
The Event Loop
Inside the web browser there is this piece of code that is used for networking. Originally, the networking code could only download one thing: the HTML page itself. When Mosaic invented the <img> tag the networking code evolved to download multiple resources. Then Netscape implemented progressive rendering of images, they had to make the networking code asynchronous so that they can draw the page before all images are loaded and update each image progressively and individually. This is the origin of the event loop.
In the heart of the browser there is an event loop that evolved from asynchronous networking code. So it's not surprising that it uses an I/O primitive as its core: select() (or something similar such as poll, epoll etc. depending on OS).
The select() function in C allows you to wait for multiple I/O operations in a single thread without needing to spawn additional threads. select() looks something like:
select (max, readlist, writelist, errlist, timeout)
To have it wait for an I/O (from a socket or disk) you'd add the file descriptor to the readlist and it will return when there is data available on any of your I/O channels. Once it returns you can continue processing the data.
The javascript interpreter saves your callback and then calls the select() function. When select() returns the interpreter figures out which callback is associated with which I/O channel and then calls it.
Conveniently, select() also allows you to specify a timeout value. By carefully managing the timeout passed to select() you can cause callbacks to be called at some time in the future. This is how setTimeout and setInterval are implemented. The interpreter keeps a list of all timeouts and calculates what it needs to pass as timeout to select(). Then when select() returns in addition to finding out if there are any callbacks that needs to be called due to an I/O operation the interpreter also checks for any expired timeouts that needs to be called.
So select() alone covers almost all the functionality necessary to implement asynchronous functions. But modern browsers also have web workers. In the case of web workers the browser spawns threads to execute javascript code asynchronously. To communicate back to the main thread the workers must still interact with the event loop (the select() function).
Node.js also spawns threads when dealing with file/disk I/O. When the I/O operation completes it communicates back with the main event loop to cause the appropriate callbacks to execute.
Hopefully this answers your question. I've always wanted to write this answer but was to busy to do so previously. If you want to know more about non-blocking I/O programming in C I suggest you take a read this: http://www.gnu.org/software/libc/manual/html_node/Waiting-for-I_002fO.html
For more information see also:
Is nodejs representing Reactor or Proactor design pattern?
Performance of NodeJS with large amount of callbacks
First of all, if something is not Async, it means it's blocking. So the javascript runner stops on that line until that function is over (that's what a readFileSync would do).
As we all know, fs is a IO library, so that kind of things take time (tell the hardware to read some files is not something done right away), so it makes a lot of sense that anything that does not require only the CPU, it's async, because it takes time, and does not need to freeze the rest of the code for waiting another piece of hardware (while the CPU is idle).
I hope this solves your doubts.
A callback is not necessarily asynchronous. Execution depends entirely on how fs.readFile decides to treat the function parameter.
In JavaScript, you can execute a function asynchronously using for example setTimeout.
Discussion and resources:
How does node.js implement non-blocking I/O?
Concurrency model and Event Loop
Wikipedia:
There are two types of callbacks, differing in how they control data flow at runtime: blocking callbacks (also known as synchronous callbacks or just callbacks) and deferred callbacks (also known as asynchronous callbacks).

Is Javascript synchronous(blocking) or Asynchronous(nonblocking) by default

I am trying to grasp on Javascript Asynchronous functions and callbacks.
I got stuck on the concept of callback functions, where I am reading on some places: they are use to have sequential execution of code (mostly in context of jquery e.g animate)and some places specially in the context of Nodejs; they are use to have a parallel execution Asynchronous and avoid blocking of code.
So can some expert in this topic please shed light on this and clear this fuzz in my mind (examples??).
so I could make my mind for the usage of callback function
or that is solely depends on the place of where you are calling/placing a callback function in your code? .
Thanks,
P.S: I am scared that this question would be close as subjective but still I could expect concrete answer for this (perhaps some examples)
Edit: actually this is the example from internet which makes me ambigous:
function do_a(){
// simulate a time consuming function
setTimeout( function(){
console.log( '`do_a`: this takes longer than `do_b`' );
}, 1000 );
}
function do_b(){
console.log( '`do_b`: this is supposed to come out after `do_a` but it comes out before `do_a`' );
}
do_a();
do_b();
Result
`do_b`: this is supposed to come out after `do_a` but it comes out before `do_a`
`do_a`: this takes longer than `do_b`
when JS is sequential then do_b should always come after do_a according to my understanding.
The core of JavaScript is largely synchronous, in that functions complete their task fully, before completing. Prior to the advent of AJAX, it was really only setTimeout and setInterval that provided asynchronous behavior.
However, it's easy to forget that event handlers are, effectively async code. Attaching a handler does not invoke the handler code and that code isn't executed until some unknowable time in the future.
Then came AJAX, with its calls to the server. These calls could be configured to be synchronous, but developers generally preferred async calls and used callback methods to implement them.
Then, we saw the proliferation of JS libraries and toolkits. These strove to homogenize different browsers' implementations of things and built on the callback approach to async code. You also started to see a lot more synchronous callbacks for things like array iteration or CSS query result handling.
Now, we are seeing Deferreds and Promises in the mix. These are objects that represent the value of a long running operation and provide an API for handling that value when it arrives.
NodeJS leans towards an async approach to many things; that much is true. However this is more a design decision on their part, rather than any inherent async nature of JS.
Javascript is always a synchronous(blocking) single thread language but we can make Javascript act Asynchronous through programming.
Synchronous code:
console.log('a');
console.log('b');
Asynchronous code:
console.log('a');
setTimeout(function() {
console.log('b');
}, 1000);
setTimeout(function() {
console.log('c');
}, 1000);
setTimeout(function() {
console.log('d');
}, 1000);
console.log('e');
This outputs: a e b c d
In node long running processes use process.nextTick() to queue up the functions/callbacks. This is usually done in the API of node and unless your programming(outside the api) with something that is blocking or code that is long running then it doesn't really effect you much. The link below should explain it better then I can.
howtonode process.nextTick()
jQuery AJAX also takes callbacks and such as it its coded not to wait for server responses before moving on to the next block of code. It just rememebers the function to run when the server responds. This is based on XMLHTTPRequest object that the browsers expose. The XHR object will remember the function to call back when the response returns.
setTimeout(fn, 0) of javascript will run a function once the call stack is empty (next available free tick) which can be used to create async like features.setTimeout(fn, 0) question on stackoverflow
To summerise the async abilities of javascript is as much to do with the environments they are programmed in as javascript itself. You do not gain any magic by just using lots of function calls and callbacks unless your using some API/script.
Jquery Deferred Object Is another good link for async capabilities of jQuery. Googling might find you information on how jQuery Deferred works also for more insight.
In JavaScript the term "asynchronous" typically refers to code that gets executed when the call stack is empty and the engine picks a job from one of its job queues for execution.
Once code is being executed, it represents a synchronous sequence of execution, which continues until the call stack is empty again. This sequence of execution will not be interrupted by events in order to execute some other JavaScript code (when we discard Web Workers). In other words, a single JavaScript environment has no preemptive concurrency.
While synchronous execution is ongoing, events might be registered as jobs in some job queues, but the engine will not process those before first properly execution what is on the call stack. Only when the call stack is empty will the engine take notice of the job queues, pick one according to priority, and execute it (and that is called asynchronous).
Callbacks
Callbacks can be synchronous or asynchronous -- this really depends on how they are called.
For instance, here the callback is executed synchronously:
new Promise(function (resolve) { /* .... */ });
And here the callback is executed asynchronously:
setTimeout(function () { /* ... */ });
It really depends on the function that takes the callback as argument; how it deals with eventually calling that callback.
Ways to get code to execute asynchronously
The core ECMAScript language does not offer a lot of ways to do this. The well-known ones are offered via other APIs, such as the Web API, which are not part of the core language (setTimeout, setInterval, requestAnimationFrame, fetch, queueMicrotask, addEventListener, ...).
Core ECMAScript offers Promise.prototype.then and (depending on that) await. The callback passed to then is guaranteed to execute asynchronously. await will ensure that the next statements in the same function will be executed asynchronously: await makes the current function return, and this function's execution context will be restored and resumed by a job.
It also offers listening to when the garbage collector is about to garbage collect an object, with FinalizationRegistry.
Web Workers
Web Workers will execute in a separate execution environment, with their own call stack. Here preemptive concurrency is possible. When the term asynchronous is used in the JavaScript world, it typically does not refer to this kind of parallelism, although the communication with a Web Worker happens via asynchronous callback functions.
Javascript by default is "synchronous", it's the web APIs that handle "asynchronous" behaviour.
As for the setTimeout example,
console.log(...), in the global scope works straight away, while those inside functions wrapped inside setTimeout, wait inside the callback queue only to be pushed back on the call stack once ready. Thus they take time. Also, the time specified is not exact but the minimum time after which that piece of code can run anytime.
Thanks !

Categories

Resources