javascript
Asynchronous JavaScript
Asynchronous programming allows JavaScript to perform long-running operations without blocking the main thread. This is essential for tasks like fetching data from servers.
Callbacks
The traditional way to handle asynchronous operations:
javascript
function fetchData(callback) {
setTimeout(() => {
const data = { name: 'John', age: 30 };
callback(data);
}, 1000);
}
fetchData((data) => {
console.log(data);
});
Callback Hell
javascript
// Nested callbacks become hard to read
getData((data) => {
processData(data, (processed) => {
saveData(processed, (result) => {
console.log('Done!');
});
});
});
Promises
Promises provide a cleaner way to handle async operations:
javascript
// Creating a promise
const myPromise = new Promise((resolve, reject) => {
setTimeout(() => {
const success = true;
if (success) {
resolve('Operation successful!');
} else {
reject('Operation failed!');
}
}, 1000);
});
// Using a promise
myPromise
.then(result => {
console.log(result);
})
.catch(error => {
console.error(error);
});
Promise States
- Pending: Initial state
- Fulfilled: Operation completed successfully
- Rejected: Operation failed
Chaining Promises
javascript
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => {
console.log(data);
return processData(data);
})
.then(processed => {
console.log(processed);
})
.catch(error => {
console.error('Error:', error);
})
.finally(() => {
console.log('Cleanup');
});
Async/Await
Modern syntax for working with promises:
javascript
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
console.log(data);
return data;
} catch (error) {
console.error('Error:', error);
}
}
fetchData();
Multiple Async Operations
javascript
// Sequential (one after another)
async function sequential() {
const data1 = await fetchData1();
const data2 = await fetchData2();
return [data1, data2];
}
// Parallel (at the same time)
async function parallel() {
const [data1, data2] = await Promise.all([
fetchData1(),
fetchData2()
]);
return [data1, data2];
}
Fetch API
Modern way to make HTTP requests:
javascript
// GET request
fetch('https://api.example.com/users')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
// POST request
fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'John',
email: 'john@example.com'
})
})
.then(response => response.json())
.then(data => console.log(data));
Complete Example
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Async JavaScript</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
.section {
background-color: #f5f5f5;
padding: 20px;
margin: 20px 0;
border-radius: 8px;
}
button {
padding: 10px 20px;
margin: 5px;
background-color: #007bff;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
button:hover {
background-color: #0056b3;
}
button:disabled {
background-color: #ccc;
cursor: not-allowed;
}
.output {
background-color: white;
padding: 15px;
margin-top: 10px;
border-radius: 5px;
min-height: 50px;
}
.loading {
color: #007bff;
font-style: italic;
}
.error {
color: #dc3545;
}
.success {
color: #28a745;
}
.user-card {
background-color: white;
padding: 15px;
margin: 10px 0;
border-radius: 5px;
border-left: 4px solid #007bff;
}
</style>
</head>
<body>
<h1>Asynchronous JavaScript</h1>
<div class="section">
<h2>Simulated API Call</h2>
<button onclick="simulateAPICall()">Fetch Data</button>
<div class="output" id="apiOutput"></div>
</div>
<div class="section">
<h2>Real API - Random User</h2>
<button onclick="fetchRandomUser()">Get Random User</button>
<div class="output" id="userOutput"></div>
</div>
<div class="section">
<h2>Multiple Requests</h2>
<button onclick="fetchMultipleUsers()">Get 3 Users</button>
<div class="output" id="multiOutput"></div>
</div>
<script>
// Simulated API Call
function simulateAPICall() {
const output = document.getElementById('apiOutput');
output.innerHTML = '<p class="loading">Loading...</p>';
// Simulate delay
setTimeout(() => {
const data = {
id: 1,
name: 'John Doe',
email: 'john@example.com',
role: 'Developer'
};
output.innerHTML = `
<div class="user-card">
<h3>${data.name}</h3>
<p><strong>Email:</strong> ${data.email}</p>
<p><strong>Role:</strong> ${data.role}</p>
<p class="success">✓ Data loaded successfully</p>
</div>
`;
}, 1500);
}
// Fetch Random User from API
async function fetchRandomUser() {
const output = document.getElementById('userOutput');
output.innerHTML = '<p class="loading">Fetching user...</p>';
try {
const response = await fetch('https://randomuser.me/api/');
const data = await response.json();
const user = data.results[0];
output.innerHTML = `
<div class="user-card">
<img src="${user.picture.large}" alt="${user.name.first}" style="border-radius: 50%; width: 100px;">
<h3>${user.name.first} ${user.name.last}</h3>
<p><strong>Email:</strong> ${user.email}</p>
<p><strong>Location:</strong> ${user.location.city}, ${user.location.country}</p>
<p><strong>Phone:</strong> ${user.phone}</p>
<p class="success">✓ User loaded successfully</p>
</div>
`;
} catch (error) {
output.innerHTML = `<p class="error">Error: ${error.message}</p>`;
}
}
// Fetch Multiple Users
async function fetchMultipleUsers() {
const output = document.getElementById('multiOutput');
output.innerHTML = '<p class="loading">Fetching 3 users...</p>';
try {
const response = await fetch('https://randomuser.me/api/?results=3');
const data = await response.json();
const users = data.results;
const usersHTML = users.map(user => `
<div class="user-card">
<img src="${user.picture.thumbnail}" alt="${user.name.first}" style="border-radius: 50%;">
<strong>${user.name.first} ${user.name.last}</strong>
<p>${user.email}</p>
</div>
`).join('');
output.innerHTML = usersHTML + '<p class="success">✓ All users loaded</p>';
} catch (error) {
output.innerHTML = `<p class="error">Error: ${error.message}</p>`;
}
}
</script>
</body>
</html>
Preview
Promise Methods
javascript
// Promise.all - wait for all promises
Promise.all([promise1, promise2, promise3])
.then(results => console.log(results));
// Promise.race - first to complete
Promise.race([promise1, promise2])
.then(result => console.log(result));
// Promise.allSettled - wait for all, regardless of outcome
Promise.allSettled([promise1, promise2])
.then(results => console.log(results));