Asynchronous Programming Concepts – Simplified
In this article, we examine some important concepts associated with asynchronous programming and their operation in web browsers and javascript.
After reading the present article, you will understand these concepts and will be ready to study the next sections of this series of educational Javascript articles.
What is asynchronous?
Typically, the code of an application runs linearly and directly, and there is only one task at a time.
If a function to run requires another function, then it needs to wait until the other function ends and returns the result, and as long as this happens, the entire program is actually stopped by the user.
For example, Mac users occasionally experience this as a spinning rainbow caster.
The operating system displaying this cursor actually states that the current program you are using should stop and wait for something else to take and it will take time to work, and hereby declare that it is not a worry and busy.
This is an unpleasant experience, and it does not take much use of computing power, especially in this era, when computers have multiple processor cores.
It’s time to wait for something else to end, while it can be left to another processing core to inform us at the end of the work.
This way you can get things done simultaneously, which is the basis of “asynchronous programming”.
Everything depends on the application environment you are using to provide asymmetrical tasks with different APIs. In the field of web programming, this is the web browser environment.
Blocking code
Asynchronous techniques are very important in programming, and especially in web programming. When a web application runs in a browser and runs a heavy batch of code without restoring control to the browser, it may seem that the browser is locked. This is called “blocking”.
In this case, the browser can not manage the user’s input and execute other tasks, and will continue until the controller returns from the processor to the browser.
For the following, we’ll look at some examples to understand the exact meaning of blocking.
In this example (+), as you see, an “event listener” is added to the button, until a button is clicked, it executes a time-consuming operation.
In this operation, 10 million dates are calculated and the result is displayed in the console. Then a paragraph will be added to the DOM.
Browser console
When you run this example, open the javascript console and then click on the button, you will notice that the paragraph will not appear on the page unless the dates are calculated and the final message is not displayed on the console.
This code is executed in the same way as it was written and the subsequent operation will not be executed until the previous operation is completed.
Note: The previous example is very unrealistic. We will never calculate a millionth date on a web application. This example is intended solely for the first idea of the subject.
In the second example (+), we simulate something that is a bit more realistic and more likely to be seen on a web page.
We block user interaction by rendering the UI. In this example we have two buttons:
A “Fill canvas” button, which when clicked, provides 1 million blue circles on the <canvas>.
A Click me for alert button that displays an alert when clicked.
If you click the first button and then quickly click on the second button, you will notice that the alert does not appear until the rendering of the circles is completed.
The first operation blocks the second operation until its completion ends.
Note: In this case, the code is ugly and our intention is merely to create a blocking mode, but this is a common problem that developers and real-world applications are always with that handwriting.
The reason for this is that javascript is a general expression of a single threaded programming language. At this stage, we must first understand the concept of thread in programming.
Yarn
The thread is basically a single process that the program can use to perform the task. Each thread can execute only one single task at a time:
Task A -> Task B -> Task C
Each task is executed in sequence and the task must be completed before the task can be started.
As we said earlier, many computers now have multithreaded processors and can therefore run multiple tasks simultaneously.
Programming languages that can support multiple threads can run multiple processor cores simultaneously to run tasks.
Thread 1: Task A -> Task B
Thread 2: Task C -> Task D
Javascript is a single language
Javascript is traditionally a single language. Even if you use multiple processor cores, you should perform tasks on a single thread, which is called the “main thread”. This example runs as follows:
Main thread: Render circles to canvas -> Display alert ()
Of course, after some time, javascript helped some of the tools to fix such problems. Web worker provides the ability to send multiple javascript processing to a single thread, called worker.
This way you can run multiple javascript code categories simultaneously. In general, a worker is used to carry out heavy work and remove this task from the original thread toe.
This way the user interaction with the browser is not blocked.
Main thread: Task A -> Task C
Worker thread: Expensive task B
Considering this, take a look at this example (+). Keep browser console open.
In fact, this example is a rewrite of the previous example, which performed 10 million dates in a separate worker thread.
Now when you click the button, the browser can display the paragraph before the dataset is completed.
Thus, the first operation does not block the second operation.
Asynchronous code
Web developers are very useful, but they also have their own limitations. The most important limitation of webcasters is that they can not access the DOM.
So you can not expect a webmaster to do anything directly to update the UI. We can not render 1 million blue circles inside the worker, since its task is merely computation.
The second problem is that although the code does not have a blocking mechanism, it still remains intact.
This situation will be problematic in cases where the function of the results of previous processing is required. Consider the following yarn diagrams:
Main thread: Task A -> Task B
In this case, Task A performs a task like fetching an image from the server, and task B performs something like applying a filter to the image.
If you begin to run task A first and then start running B immediately, you will encounter an error, because the image is still not ready.
Main thread: Task A -> Task B -> | Task D |
Worker thread: Task C ———–> | | |
In this case, suppose that task D uses the results of both tasks B and C. If we can ensure that these results are both ready at the same time, then there will be no problem, but such a situation is unlikely.
If task D attempts to run when its input is not yet ready, it will run with an error.
Browser asynchronous features
Browsers allow us to perform some operations asynchronously to correct such errors.
Functions such as Promises allow you to specify an executable mode for an operation (for example, fetch an image from the server), and then wait to return the result before executing the next operation:
Main thread: Task A Task B
Promise: | __async operation__ |
Since the operation takes place elsewhere, while the asynchronous operation is being processed, the thread is not blocked. In the next section of this series of tutorials we will look at ways to write asynchronous codes.
Ending speech
The principles of modern software development are increasingly being developed around the use of asynchronous programming so that programs can perform multiple tasks simultaneously.
When you use more modern and powerful APIs, you’ll find more than just the way to run an asynchronous programmer task.
Writing asynchronous code is more difficult, and getting used to it takes a bit of time, but it’s going to be easier.
In the next sections of this series, we will look at why the importance of asynchronous code and code design methods prevent the problems encountered in this paper.