Asynchronous Javascript
Synchronous execution
Basically, referring to a programming language, Synchronous means executing tasks one at a time in the order described by the source code. This means we cannot execute a certain operation until the previous one has finished.
However, in modern web applications, this kind of behavior would have a great impact on usability given the fact that certain tasks (such as communicating via network) might take an unreasonable time to complete, blocking the main thread of execution.
JavaScript engines consist of 3 main components:
Global Memory
Thread of execution
Call Stack
Based on the order in the code, they push functions in the Call Stack, they execute them, while eventually reading or writing from the memory, one at a time, and then pop the function moving to the following one until the code is over.
Asynchronous execution
Luckily, JavaScript Runtimes (such as browsers or NodeJS) have important additions to the core JavaScript engine, allowing an Asynchronous behavior.
Some of the features that aren't native in JavaScript, but available through a browser runtime are:
the console
rendering the HTML DOM
a timer
making requests via the network
Triggering their executions within the browser's background processes from JavaScript is possible with certain APIs, such as in the following examples:
console.log()
triggers the browser to display the evaluation between the bracketsdocument.getElementsById()
allows us to manipulate the way the DOM is being renderedsetTimeout(expensiveOperation, 3000)
orsetInterval()
start a timer in a background browser processXMLHttpRequest()
and the more recentfetch()
allows us to issue network requests and retrieve external answers
The order in which the runtime executes code
With the use of the Event Loop, which basically keeps asking if the main thread's call stack got emptied, the tasks in the MicroTask queue are being executed and popped until the queue gets empty, followed by the Callback queue tasks.
By continuously feeding the Microtask queue, there is a risk (more likely when in NodeJS) to "starve" the Callback queue.
Asynchronicity is achieved through 3 methods
Callbacks
Promises
Async Await
Promises
A Promise
is an object representing the eventual completion or failure of an asynchronous operation.
Essentially, a promise is a returned object to which you attach callbacks, instead of passing callbacks into a function. When a Promise
is created, the object, stored in the Global Memory, contains some hidden properties and methods.
The returned value if the Promise is fulfilled
An array of callbacks which is immediately pushed to the MicroTask queue, once the value is returned, the first of those taking the value as the single argument
An array of callbacks that are pushed to the MicroTask queue if the Promise chain is rejected.
These arrays of functions are basically chained functions. The resolve Array is created using the .then()
method while the rejected array is created using the .catch()
method.
Async/await
The async
keyword can be placed before a function, which will return a promise. The returned values of the function will be wrapped in a resolved promise automatically.
The keyword await
makes JavaScript wait until that promise settles and returns its result.
await
literally suspends the function execution until the promise settles, and then resumes it with the promise result. It’s just a more elegant syntax of getting the promise result than promise.then
, easier to read and write.
Last updated
Was this helpful?