async-await-and-error-handling
- For TypeScript, please give 15 key points, tips and tricks I should know for a job interview for what we should know about Async/Await and Error Handling
Async/Await and Error Handling:
Async/await:
The async/await pattern in TypeScript allows you to write code that handles asynchronous operations in a sequence that looks like standard synchronous code.
async function fetchData() {
const data = await someAsyncDataFunction();
console.log(data);
}Async functions:
Functions defined with the
async
keyword return a promise, and the resolved value is what the function returns.async function getNumber(): Promise<number> {
return 42;
}Await keyword:
The
await
keyword pauses the function's execution until the promise is settled, then resumes with the promise's result.async function showData() {
const data = await fetchData(); // Waits here until fetchData resolves
console.log(data);
}Code readability:
Using async/await helps in writing cleaner code as it avoids nesting then-callbacks.
// Instead of chaining with .then()
fetchData().then(data => {
console.log(data);
});
// You can write
async function displayData() {
const data = await fetchData();
console.log(data);
}Error handling:
Async functions can use try/catch blocks for error handling, which can make error handling logic clearer.
async function safeFetch() {
try {
const data = await fetchData();
console.log(data);
} catch (error) {
console.error("An error occurred:", error);
}
}Type checking:
TypeScript checks the types within async functions, ensuring that the returned promise resolves to the expected type.
async function fetchTypedData(): Promise<string> {
return await someStringReturningAsyncFunction();
}Error propagation:
In async functions, errors from rejected promises are thrown, similar to throwing exceptions in synchronous code.
async function riskyFetch() {
const data = await fetchWithPossibleRejection(); // This can throw
return data;
}
```- **Return types:**
The return type of an async function is always a Promise. You can specify the type that the Promise will resolve to.
```typescript
async function fetchJson(url: string): Promise<JsonType> {
const response = await fetch(url);
return response.json();
}Unhandled rejections:
Always handle promise rejections to avoid runtime errors. This can be done within the async function or at the call site.
async function fetchDataSafely() {
try {
const data = await fetchData();
return data;
} catch (error) {
console.error("Caught an unhandled rejection:", error);
}
}Control flows:
Async/await makes it easier to write control flows for asynchronous operations, like waiting for multiple promises in sequence or parallel.
async function sequentialStart() {
const first = await firstAsyncOperation();
const second = await secondAsyncOperation(first);
return second;
}
async function parallelStart() {
const [firstResult, secondResult] = await Promise.all([
firstAsyncOperation(),
secondAsyncOperation(),
]);
return { firstResult, secondResult };
}Type inference:
TypeScript infers the type within an async function from the awaited expressions, which helps in maintaining a strong type system.
async function getNumber(): Promise<number> {
const num = await Promise.resolve(42);
return num; // TypeScript infers `num` as `number`
}Performance consideration:
Use async/await wisely; in cases where operations could run concurrently, use
Promise.all
to run them in parallel.async function fetchDataInParallel(urls: string[]) {
return Promise.all(urls.map(url => fetch(url).then(resp => resp.json())));
}Combining with promises:
Async functions can be used alongside traditional promise chains if needed.
async function fetchDataWithThen() {
const data = await fetchData();
data.then(processData).catch(handleError);
}Strict mode compatibility:
Async/await is compatible with TypeScript's strict mode, which can help catch potential issues at compile time.
// In strict mode, TypeScript will enforce more rigorous checks
Asynchronous iteration:
Use the
for-await-of
loop to iterate over data that is received asynchronously, such as streams.async function processAsyncIterable(iterable: AsyncIterable<Type>) {
for await (const item of iterable) {
processItem(item);
}
}
Mastering async/await and proper error handling in TypeScript is key to writing high-quality asynchronous code that is both robust and easy to maintain.