Scalability is a key factor in system design, especially when the system has to handle a large number of requests. One of the important techniques to achieve scalability is the use of asynchronism.
Imagine you want to buy a loaf of bread at your favorite bakery. You walk into the store, ask for a loaf of bread, but the clerk says it’s not available yet! Instead, you’re asked to come back in 2 hours when your bread is ready.
This is a simple example of a Synchronous model. You have to wait until the cake is baked before you can pick it up. If many people come to buy cakes and each person has to wait 2 hours, the bakery will be very slow and will have difficulty serving many customers at the same time.
Now, imagine another scenario. You go to the bakery, take an order number, and place your order. You can go about your business, and when your cake is ready, you will receive a text message. You return to the bakery, give your order number, and pick up your cake.
This is an example of the Asynchronous model. You don't have to wait directly. You can do other things while the cake is baking, and you only come back when it's ready. This allows the bakery and you to do more things at the same time, because they don't have to keep customers waiting.
In programming, asynchrony is a method that allows a program to perform multiple tasks at the same time without waiting for the previous task to complete. Instead of waiting, the program can send a request and continue to perform other tasks. When the request is completed, the program receives a notification (e.g., via a callback or promise) and processes the result.
The main difference between synchronous and asynchronous:
Using asynchrony has many benefits, especially in highly loaded systems:
There are different techniques for implementing asynchrony, depending on the programming language and platform you use.
Callbacks are one of the most classic asynchronous techniques. A callback is a function that is passed as an argument to another function. The original function calls the callback when the asynchronous task completes.
Example (JavaScript):
function fetchData(url, callback) {
makeHttpRequest(url, function(data) {
callback(data);
});
}
fetchData('https://example.com/data', function(data) {
console.log('Done:', data);
});
Callbacks can become complex and difficult to manage when there are many nested asynchronous tasks (callback hell).
Promises are objects that represent the eventual result of an asynchronous operation. A Promise can be in one of three states: pending, fulfilled, or rejected.
Example (JavaScript):
function fetchData(url) {
return new Promise(function(resolve, reject) {
makeHttpRequest(url, function(data, error) {
if (error) {
reject(error);
} else {
resolve(data);
}
});
});
}
fetchData('https://example.com/data')
.then(function(data) {
console.log('Done:', data);
})
.catch(function(error) {
console.error('Error:', error);
});
Promises help make asynchronous code more readable and manageable than callbacks.
Async/Await is a newer syntax in JavaScript, built on top of Promises. It allows you to write asynchronous code that looks like synchronous code.
Example (JavaScript):
async function fetchData(url) {
try {
const data = await makeHttpRequest(url);
return data;
} catch (error) {
console.error('Error:', error);
}
}
async function processData() {
const data = await fetchData('https://example.com/data');
console.log('Done:', data);
}
processData();
Async/Await makes writing and reading asynchronous code even easier.
Message queues are a method for sending messages between different components of a system. The components do not need to communicate directly with each other; instead, they send and receive messages from queues.
For example:
The OrderService can use a queue to send orders from the web application to the PaymentService. The web application does not need to wait for the payment processing system to complete; it can simply send the message to the queue and continue processing other requests.
Popular message queue technologies include RabbitMQ, Kafka, and Redis.
Asynchrony is widely used in many types of applications:
Asynchrony is a powerful technique for increasing the scalability and responsiveness of a system. By allowing tasks to be executed in parallel, it helps the system use resources more efficiently and handle more requests at the same time. From using callbacks and promises to async/await and message queues, there are many different ways to implement asynchrony, depending on the specific needs and requirements of your project. Hopefully, the bakery example and the detailed explanation above have helped you better understand the concept and how to apply it in practice.