TypeScript Async Programming
Working with asynchronous operations using Promises and async/await
⏱️ What is Async Programming?
Asynchronous programming allows your code to handle time-consuming operations without blocking execution. TypeScript provides strong typing for Promises, async/await, and callbacks, making asynchronous code safer and more predictable.
// Simple async function
async function fetchUser(id: number): Promise<string> {
return new Promise((resolve) => {
setTimeout(() => {
resolve(`User ${id}`);
}, 1000);
});
}
// Using await
const user = await fetchUser(1);
console.log(user); // "User 1"
Output:
User 1
Async Programming Concepts
Promises
Represent future values
const promise: Promise<number> =
Promise.resolve(42);
Async/Await
Write async code like sync code
async function getData() {
return await fetch('/api');
}
Promise Chaining
Chain multiple async operations
promise
.then(x => x * 2)
.then(x => x + 1);
Parallel Execution
Run multiple promises together
await Promise.all([
fetch('/api/1'),
fetch('/api/2')
]);
🔹 Creating Promises
Promises represent values that will be available in the future:
// Basic Promise with type
function delay(ms: number): Promise<void> {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
// Promise that returns a value
function fetchData(): Promise<string> {
return new Promise((resolve, reject) => {
const success = true;
if (success) {
resolve("Data loaded successfully");
} else {
reject("Failed to load data");
}
});
}
// Using the promise
fetchData()
.then(data => console.log(data))
.catch(error => console.error(error));
Output:
Data loaded successfully
🔹 Async/Await Syntax
Async/await makes asynchronous code look synchronous:
// Define an async function
async function getUserData(userId: number): Promise<object> {
// Simulate API call
await delay(1000);
return {
id: userId,
name: "John Doe",
email: "[email protected]"
};
}
// Call async function
async function displayUser() {
console.log("Fetching user...");
const user = await getUserData(1);
console.log("User:", user);
console.log("Done!");
}
displayUser();
Output:
Fetching user...
User: { id: 1, name: "John Doe", email: "[email protected]" }
Done!
🔹 Typing Async Functions
TypeScript provides strong typing for async operations:
// Async function with typed return
async function getNumber(): Promise<number> {
return 42;
}
// Async function with typed parameters
async function processUser(
id: number,
name: string
): Promise<{ success: boolean; message: string }> {
await delay(500);
return {
success: true,
message: `Processed user ${name} with ID ${id}`
};
}
// Using the typed async function
const result = await processUser(1, "Alice");
console.log(result.message);
Output:
Processed user Alice with ID 1
🔹 Parallel Execution
Run multiple async operations simultaneously:
// Multiple async operations
async function fetchUser(id: number): Promise<string> {
await delay(1000);
return `User ${id}`;
}
async function fetchPosts(userId: number): Promise<string[]> {
await delay(1000);
return [`Post 1`, `Post 2`, `Post 3`];
}
// Sequential (slow - 2 seconds total)
async function sequentialFetch() {
const user = await fetchUser(1); // Wait 1 second
const posts = await fetchPosts(1); // Wait 1 second
return { user, posts };
}
// Parallel (fast - 1 second total)
async function parallelFetch() {
const [user, posts] = await Promise.all([
fetchUser(1), // Both run
fetchPosts(1) // at the same time
]);
return { user, posts };
}
const data = await parallelFetch();
console.log(data);
Output:
{ user: "User 1", posts: ["Post 1", "Post 2", "Post 3"] }
🔹 Error Handling
Handle errors in async code with try/catch:
// Async function that might fail
async function riskyOperation(): Promise<string> {
const random = Math.random();
if (random > 0.5) {
return "Success!";
} else {
throw new Error("Operation failed");
}
}
// Handle errors with try/catch
async function safeOperation() {
try {
const result = await riskyOperation();
console.log(result);
} catch (error) {
if (error instanceof Error) {
console.error("Error:", error.message);
}
} finally {
console.log("Operation completed");
}
}
safeOperation();
Output (varies):
Success! Operation completed OR Error: Operation failed Operation completed
🔹 Common Patterns
Useful async programming patterns:
Promise.all() - Wait for all
const results = await Promise.all([promise1, promise2, promise3]);
Promise.race() - First to finish
const fastest = await Promise.race([promise1, promise2]);
Promise.allSettled() - All results (success or failure)
const outcomes = await Promise.allSettled([promise1, promise2]);
Promise.any() - First successful
const firstSuccess = await Promise.any([promise1, promise2]);