Write asynchronous code in a breeze with async and await
Writing asynchronous code is very common these days. Callback structured code can be difficult to read, write and maintain. Promises were a step forward. async and await makes writing (and reading) asynchronous code a breeze!
In this post we are going to explore some sample asynchronous code using async
and await
in TypeScript.
Asynchronous Functions
Asynchronous code that calls a web service is pretty common these days. So, let’s create an asynchronous function that calls a web service to get some data using async
and await
.
There are 3 main points of note in our function:
- Our function contains a call to the
fetch
function. Theawait
keyword allowsfetch
to be called in an asynchronous manner with the execution of the next line blocked untilfetch
returns - Our function is prefixed with the
async
keyword because we are referencing theawait
keyword and executing asynchronous code within our function. Theasync
keyword allows our function to be called in an asynchronous manner withawait
- Our
async
function needs to return aPromise
async function getData(resource: string): Promise<IResourceData> {
const response = await fetch(`https://somedomain/${resource}`);
const data: IResourceData = await response.json();
return data;
}
// somewhere else in the code ...
const data: IResourceData = await getData("contact");
Neat!
Asynchronous Arrow Functions
But what if we want to write an arrow function? Here’s the same function as an arrow function:
const getData = async (resource: string): Promise<IResourceData> => {
const response = await fetch(`https://somedomain/${resource}`);
const data: IResourceData = await response.json();
return data;
};
Handling Errors
What if the web service call errors? We simply use try ... catch
as if the code was synchronous.
try {
const response = await fetch(`https://somedomain/${resource}`);
const data: IResourceData = await response.json();
return data;
} catch (ex) {
// handle the error
}
Several async calls in a loop
What if we need to make asynchronous calls in a loop and need to wait for all the calls to complete before continuing execution? Promise.all
is what we need.
The example below executes a set of asynchronous validation rules for a field. Promise.all
is used to make sure all the validation rule checks have been completed before the user is informed of any problems. Note that we also need the async
keyword prefixing the function that map
is operating on.
...
await Promise.all(validations.map(async (validation: IFieldValidator) => {
if (validation && validation.rule) {
const newError: string = await validation.rule(values, fieldName, validation.args);
if (newError) {
errors.push(newError);
}
}
}));
...
// inform the user of any problems
...
Wrapping up
async
and await
allows us to write asynchronous code very similar to how we would write synchronous code. This makes the code easy to read and write. TypeScript’s async & await gives great browser support as well (including IE). So, well worth considering for any asynchronous code we need to write today.
If you to learn more about TypeScript, you may find my free TypeScript course useful: