Basically, asynchronization has two layers of meaning 1) unblocking of slow operations; and 2) triggering events non-linearly. In OS terms, the event is also called an interruption that can represent a coming network packet, a clock tick, or simply a mouse click. Technically, the event interrupts the current process, puts the next CPU instruction on hold, and calls a predefined code block (a.k.a., an event handler), “asynchronously”.
The concept is essentially the same in application level.
Before we start experimenting on JS, let’s do some preparations.
Secondly, we use python (Flask) to simulate a slow API which sleeps ten seconds for each request to impose noticeable latency:
Now we toggle the CORS plug-in to “on” (otherwise the network request will fail instantly) and run the example:
By debugging the code, we can observe that that after the network request, the code is suspended at the following line:
for >10 seconds and the button is not clickable at all before it displays the result:
Moreover, the runtime (I’m using Chrome) complaints:
which can be an official statement of the problem.
Broadly speaking, asychronization can be 1) (slow) operations that are performed from another thread; or 2) events that are triggered from external; or the composite of both. I am introducing three examples to demonstrate asychronization in code:
The code used by this example also can solve the problem discussed in the previous section:
In this example, we 1) change the second parameter to “true” so as to offload the slow network interaction to another thread, and 2) register a callback as an event handler for the response packet. The callback will be effectively triggered from the other thread when the network interaction completes.
This time, the button can respond to a user’s click throughout the process and
is displayed after the send as expected.
In all the three examples, we register handlers (a.k.a., callbacks) for certain events occurred outside of the main thread. In the first example, we also offload a slow operation to an external thread to fight the blocking problem. As mentioned, all operations can be abstracted in one word, asynchronization!
In the first example, packet arrival, I use a callback to make the operation more obvious as asynchronized. A better practice of sending network request is to use the newer API — fetch(). The function returns a Promise that can call then() in turn, so that
- the asynchronized operation can be coded in a synchronized manner (thus less obvious), and
- the so dubbed “callback hell” can be effectively avoided, and the best part
- all the potential exceptions involved in multiple asynchronized calls can be handled in one place:
The result is the same as the example one, and I leave the button there for you to click.
The answer is yes and no. I’ll explain:
Assuming the browser’s pid is 666, we can use a simple script (I’m using Mac) to monitor the status of threads belonging to the browser :
initial values (I beautified the output a bit by removing the irrelevant columns and rows):
values when I stop:
Besides the main thread, there is another thread that is pretty active during the process, which indicate that one more thread is involved, most likely, by sending the network request and listening to the multiplex socket.
We look at a frequent example first:
We know that the result is:
To recap, though we register a time event and indicate the callback should be invoked immediately, the runtime still waits for the current “loop” iteration to finish before it executes the callback from an “event queue”.
Does the coarse-grained event handling slow down the speed that an UI component can respond to a user’s operation? I think no. Even with the system level interruption, a user’s operation can be reflected on the UI after a “loop circle”, as UI updating can be only performed from the main thread. Thus, this simplified, single threaded event loop design itself does not impose penalties on UI performance. What do you think?
which signals its importance.
Then we come to this one that demystifies the asynchronization operation.