Transitioning to TypeScript: The Ultimate Starter Guide - Part 5
TypeScript from JavaScript Part 5 of 7: Async/Await and Error Handling
Hello again, fellow developers! We have already covered a lot in our journey from JavaScript to TypeScript: basic and advanced types, modules, namespaces, decorators, and type guards. In this part, we will dive into one of the most powerful features of modern JavaScript and TypeScript: async/await and error handling.
As always, remember that the purpose of this series is not just to learn TypeScript, but to understand how it can simplify our work, save time, and elevate our apps. So, let's get started!
1. Understanding Promises
Before we dive into async/await, it's important to have a good understanding of Promises, as async/await is built on top of them.
A Promise in JavaScript (and therefore in TypeScript) is an object that represents the eventual completion or failure of an asynchronous operation. It is a way to handle asynchronous operations like HTTP requests, reading files, or timers, and allows us to write non-blocking code.
Here is how you create a Promise:
const promise = new Promise((resolve, reject) => {
const success = true;
if (success) {
resolve('The operation was successful.');
} else {
reject('The operation failed.');
}
});
promise.then((message) => {
console.log('Success:', message);
}).catch((message) => {
console.log('Failure:', message);
});
In this example, we create a Promise that either resolves or rejects based on the value of the success
variable. If the operation is successful, we call the resolve
function, otherwise, we call the reject
function. We can then use the then
method to handle the resolved value and the catch
method to handle the rejected value.
2. Async/Await
Async/await is a modern way to work with Promises. It makes asynchronous code look and behave a little more like synchronous code, which makes it easier to read and understand.
a. Async Functions
An async function is a function declared with the async
keyword. Async functions are instances of the AsyncFunction
constructor, and the await
keyword is permitted within them.
async function myFunction() {
return 'Hello, World!';
}
myFunction().then((value) => {
console.log(value); // Hello, World!
});
In this example, myFunction
is an async function that returns a resolved Promise with the value 'Hello, World!'
. We can then use the then
method to handle the resolved value.
b. Await
The await
keyword is used to pause and resume a JavaScript AsyncFunction
and to wait for the Promise's resolution or rejection.
async function myFunction() {
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Hello, World!');
}, 2000);
});
const result = await promise;
console.log(result);
}
myFunction();
In this example, myFunction
is an async function that creates a Promise that resolves after 2 seconds. The await
keyword is used to wait for the Promise to resolve before logging the result to the console.
3. Error Handling
Error handling is crucial for any application. In asynchronous code, errors can occur in two ways: synchronous errors (e.g., type errors, syntax errors) and asynchronous errors (e.g., network errors, timeout errors).
a. Try/Catch
The try/catch statement allows you to define a block of code to be tested for errors while it is being executed (try), and a block of code to be executed if an error occurs (catch).
async function myFunction() {
try {
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
reject('Something went wrong.');
}, 2000);
});
const result = await promise;
console.log(result);
} catch (error) {
console.error(error);
}
}
myFunction();
In this example, myFunction
is an async function that creates a Promise that rejects after 2 seconds. The await
keyword is used to wait for the Promise to resolve or reject. If the Promise resolves, the result is logged to the console. If the Promise rejects, the error is caught and logged to the console.
b. Error Propagation
In asynchronous code, it's important to propagate errors up the call stack so they can be handled properly.
async function myFunction() {
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('Something went wrong.'));
}, 2000);
});
const result = await promise;
return result;
}
async function main() {
try {
const result = await myFunction();
console.log(result);
} catch (error) {
console.error(error.message);
}
}
main
();
In this example, myFunction
is an async function that creates a Promise that rejects after 2 seconds. The main
function is another async function that calls myFunction
and handles any errors that occur.
Conclusion
In this part, we have learned about async/await and error handling in TypeScript. We have learned how to create async functions, how to use the await
keyword to wait for Promises to resolve or reject, and how to handle errors using try/catch and error propagation.
Stay tuned for the next part of this series, where we will dive into advanced topics like generics and utility types!
Happy coding! 💻✨