Documentation Index
Fetch the complete documentation index at: https://mintlify.com/diegoromemora27-creator/HTMLCSSEXPLAIN/llms.txt
Use this file to discover all available pages before exploring further.
What is Async/Await?
Async/await is a modern way to handle asynchronous operations (like API calls) that makes your code look synchronous and easier to read.
async → Marks a function as asynchronous (it can wait for things)
await → “Wait here until this Promise resolves”
What is a Promise?
A Promise is like a “ticket” for a future value. Think of ordering food:
- You order → You get a receipt (Promise)
- You wait → The promise is “pending”
- Food arrives → The promise is “resolved” with your food
Or the kitchen runs out → The promise is “rejected” with an error
Basic Syntax
async function functionName(): Promise<ReturnType> {
const result = await asynchronousOperation();
return result;
}
Real Example: Fetching Products
From our project, here’s how we fetch products from an API:
// async function → This function is asynchronous
// Promise<Product[]> → It promises to return an array of Products
// limit: number = 20 → Parameter with default value
async function fetchProducts(limit: number = 20): Promise<Product[]> {
// Template literal: build the URL with the limit
const url = `${API_URL}?limit=${limit}`;
console.log(`Fetching: ${url}`);
// await fetch(url) → Wait for the server to respond
// response is of type Response (object with metadata + methods)
const response = await fetch(url);
// Check if response was successful (status 200-299)
if (!response.ok) {
// If not successful, throw an error with HTTP code
throw new Error(`HTTP Error: ${response.status}`);
}
// await response.json() → Wait and parse the JSON
// as Product[] → Tell TypeScript the JSON is a Product array
const data = await response.json() as Product[];
console.log(`Products received: ${data.length}`);
// Return the products
return data;
}
The Fetch Flow
Your App API Server
│ │
│──── fetch(url) ────────>│ 1. Send request
│ (await) │ 2. Wait...
│<──── Response ──────────│ 3. Receive response
│ │
│── response.json() ─────>│ 4. Parse JSON
│ (await) │ 5. Wait...
│<──── Data[] ────────────│ 6. We have the data!
Without Async/Await (Old Way)
Before async/await, we used .then() chains:
// ❌ Hard to read
function fetchProducts(limit: number): Promise<Product[]> {
return fetch(`${API_URL}?limit=${limit}`)
.then(response => {
if (!response.ok) {
throw new Error(`HTTP Error: ${response.status}`);
}
return response.json();
})
.then(data => {
console.log(`Products received: ${data.length}`);
return data;
});
}
With Async/Await (Modern Way)
// ✅ Much easier to read!
async function fetchProducts(limit: number): Promise<Product[]> {
const response = await fetch(`${API_URL}?limit=${limit}`);
if (!response.ok) {
throw new Error(`HTTP Error: ${response.status}`);
}
const data = await response.json();
console.log(`Products received: ${data.length}`);
return data;
}
Error Handling with Try/Catch
Use try/catch to handle errors gracefully:
async function loadProducts(): Promise<void> {
// 1. Update state to "loading"
appState.status = LoadingState.Loading;
appState.error = null; // Clear any previous error
updateUI(); // Reflect change in UI (shows spinner)
// 2. Try to load products (might fail)
try {
// await waits for fetchProducts to finish
const products = await fetchProducts(20);
// If we get here, loading was successful
appState.status = LoadingState.Success;
appState.products = products;
} catch (error) {
// If something fails (network, server, etc.), we arrive here
// Check if 'error' is an Error instance to access .message
// If not Error (could be a string or something else), use generic message
appState.error = error instanceof Error ? error.message : "Unknown error";
appState.status = LoadingState.Error;
// Log error to console for debugging
console.error("Error loading products:", error);
}
// 3. Update UI (whether success or error)
updateUI();
}
When to Use Async/Await
Use async/await for operations that take time:
- API calls (fetch, axios)
- Database queries
- File operations
- Timers (setTimeout as Promise)
- Any function that returns a Promise
Multiple Awaits (Sequential)
When you need things to happen in order:
async function processOrder() {
const user = await fetchUser(); // Wait for user
const cart = await fetchCart(user.id); // Then get cart (needs user.id)
const order = await createOrder(cart); // Then create order (needs cart)
return order;
}
Multiple Awaits (Parallel)
When things can happen at the same time:
async function loadPageData() {
// These don't depend on each other - run them in parallel!
const [products, categories, user] = await Promise.all([
fetchProducts(),
fetchCategories(),
fetchUser()
]);
return { products, categories, user };
}
Return Type: Promise<T>
Async functions always return a Promise:
async function fetchProducts(): Promise<Product[]> {
// Even though we return Product[], the function returns Promise<Product[]>
return data;
}
// To use it:
const products = await fetchProducts(); // products is Product[]
Async Functions Can’t Run in Regular Functions
// ❌ Error: 'await' is only valid in async functions
function loadData() {
const data = await fetchProducts(); // Error!
}
// ✅ Correct: Mark the function as async
async function loadData() {
const data = await fetchProducts(); // Works!
}
Common Pattern: Loading State Management
Combine async/await with enums for clean state management:
async function loadData(): Promise<void> {
// Start loading
setState(LoadingState.Loading);
try {
// Fetch data
const data = await fetchData();
// Success
setState(LoadingState.Success);
setData(data);
} catch (error) {
// Error
setState(LoadingState.Error);
setError(error.message);
}
}
Async/Await with Event Listeners
You can use async functions with event listeners:
function setupEventListeners(): void {
const loadBtn = getElement<HTMLButtonElement>("#load-products-btn");
// loadProducts is async - that's fine!
loadBtn.addEventListener('click', loadProducts);
}
When the button is clicked, loadProducts runs asynchronously.
Error Types and Instanceof
Check error types safely:
try {
const data = await fetchProducts();
} catch (error) {
// error could be anything (Error, string, number, etc.)
// Check if it's an Error instance to access .message
if (error instanceof Error) {
console.error(error.message); // Safe to access .message
} else {
console.error("Unknown error:", error);
}
}
HTTP Status Codes
Common codes you’ll encounter:
| Code | Meaning |
|---|
| 200 | OK (success) |
| 201 | Created (resource created successfully) |
| 400 | Bad Request (invalid data sent) |
| 401 | Unauthorized (need to log in) |
| 404 | Not Found (resource doesn’t exist) |
| 500 | Internal Server Error (server problem) |
const response = await fetch(url);
if (!response.ok) {
// response.status has the HTTP code (404, 500, etc.)
throw new Error(`HTTP Error: ${response.status}`);
}
Default Parameters
Provide default values for parameters:
// limit: number = 20 → If no limit provided, use 20
async function fetchProducts(limit: number = 20): Promise<Product[]> {
const url = `${API_URL}?limit=${limit}`;
// ...
}
// Usage:
await fetchProducts(); // Uses default: 20
await fetchProducts(10); // Uses provided: 10
Next Steps