Async JS
JavaScript isn’t just about synchronous code — mastering asynchronous patterns is essential. Below is a complete guide covering Callbacks, Functional Arguments, Callback Hell, and the Event Loop.
Asynchronous JavaScript – The Problem
JavaScript is single-threaded, so blocking operations (e.g., reading files) would freeze the entire app if handled synchronously.
Instead, JavaScript uses asynchronous patterns to handle such tasks without blocking the main thread.
Illustration – File I/O: Sync vs Async
Synchronous File Read (Blocking)
const fs = require('fs');
console.log('Start reading file synchronously');
const data = fs.readFileSync('./large-file.txt', 'utf8');
console.log('File content length:', data.length);
console.log('Finished synchronous read');- The process blocks until the file is fully read.
- Nothing else can execute during the read.
- Total time depends entirely on file size.
Asynchronous File Read (Non-blocking)
const fs = require('fs');
console.log('Start reading file asynchronously');
fs.readFile('./large-file.txt', 'utf8', (err, data) => {
if (err) {
console.error('Error reading file:', err);
return;
}
console.log('File content length:', data.length);
});
console.log('Finished initiating async read');Expected Output Order:
Start reading file asynchronously
Finished initiating async read
File content length: 1234567Functional Arguments
A functional argument is a function passed into another function as an argument. It allows the receiving function to call it when needed, providing a flexible way to handle asynchronous or deferred execution.
Example
function greet(name, formatter) {
console.log(formatter(name));
}
function uppercase(name) {
return name.toUpperCase();
}
greet('Alice', uppercase); // Outputs: ALICECallbacks
A callback is a function passed as an argument to another function to be executed after some asynchronous task completes.
Example Using Functional Argument with fs.readFile
const fs = require('fs');
function readFileAsync(filePath, callback) {
fs.readFile(filePath, 'utf8', (err, data) => {
callback(err, data);
});
}
console.log('Start reading file asynchronously');
readFileAsync('./large-file.txt', (err, data) => {
if (err) {
console.error('Error:', err);
return;
}
console.log('File content length:', data.length);
});
console.log('File read initiated');Callback Hell
When multiple asynchronous tasks depend on each other, using callbacks leads to deeply nested code — a situation called Callback Hell.
const fs = require('fs');
fs.readFile('./file1.txt', 'utf8', (err, data1) => {
if (err) return console.error('Error reading file1:', err);
fs.readFile('./file2.txt', 'utf8', (err, data2) => {
if (err) return console.error('Error reading file2:', err);
fs.readFile('./file3.txt', 'utf8', (err, data3) => {
if (err) return console.error('Error reading file3:', err);
console.log('All files read:', data1.length, data2.length, data3.length);
});
});
});Synchronous File Read with Functional Argument
const fs = require('fs');
function readFileSyncWithCallback(filePath, callback) {
try {
const data = fs.readFileSync(filePath, 'utf8');
callback(null, data);
} catch (err) {
callback(err, null);
}
}
console.log('Start reading file synchronously');
readFileSyncWithCallback('./large-file.txt', (err, data) => {
if (err) {
console.error('Error:', err);
} else {
console.log('File content length:', data.length);
}
});
console.log('Finished synchronous read');Event Loop – How Async JS Works
- Call Stack executes synchronous code.
- Async APIs (e.g.,
fs.readFile,setTimeout) run in Web APIs. - Their callback moves to the Task Queue when ready.
- Event Loop moves tasks from the queue to the Call Stack.
console.log("Start");
setTimeout(() => {
console.log("Async Timeout");
}, 0);
console.log("End");
// Output:
// Start
// End
// Async TimeoutSyntax and Complex Types
JavaScript is flexible, powerful, and sometimes quirky. Below is a comprehensive guide covering syntax basics, complex types, and advanced structures you need to understand to write maintainable code.
Promises, Async/Await
Explore Promises, Async/Await, Promise.all, Promise.race, and proper error handling in asynchronous JavaScript.