Welcome to today’s post.
In today’s post I will be showing two different ways in which we can asynchronously wait for a service call or a web API HTTP REST call within an Angular application.
In a recent post I showed how to use the RxJS subscribe operator to execute a service call through an observable. This is quite a common way to call services and await results. An alternative way to call a service and await its result and completion is to use the async … await keywords that are available in JavaScript since ECMAScript 2017.
Remember the Legacy JavaScript Promise?
If you have ever used the Promise object, which is a global object that stores the completion or failure state of an asynchronous operation, then using async and await will be straightforward, and even if you are a web developer using more recent development tools and libraries, it will be easy to adapt to. I will show how later with some examples. The definition of the Promise object is the eventual completion (or the failure) of an asynchronous operation and its resulting value.
By definition, a Promise has three states:
Pending, the initial state.
Fulfilled, the completion state.
Rejected, the failure state.
When a Promise completes, it will include a value.
When a Promise fails, it will return an error. There are two common Promise methods used to process fulfilled or rejected, these are the then() and catch() methods respectively. Promise objects are commonly chained
together using the then() method to pass the intermediate results of asynchronous operations through a chain. When a promise returns and fulfills, an arrow function is used to process the results returned from the service call.
So, a call like the one below:
aPromise.then(value =>
{
Console.log(value);
return 'the value returned is : ' + value;
});
The above methods can also be chained. An example is chaining then() and catch() methods to process a completion and catch any potential errors from the service call:
aPromise.then(value =>
{
console.log(value);
return 'the value returned is : ' + value;
})
.catch(err => {
console.log('the error returned is : ' + err);
});
In the next section, I will show how to use a modern variation of the Promise object.
The Modern Async and Await Pattern
The definition of the async and await pattern used within JavaScript allows a function and the code within its body to run asynchronously.
To return a promise from a function, we prefix the function name with the async keyword, like the one below:
async function aFunction() {
…
}
To run code asynchronously within the asynchronous function we prefix a call with the await keyword:
async function aFunction() {
…
await aCall();
…
}
So, the calling method or function can be made to wait on the promise being fulfilled by prefixing the function call with the await keyword.
Suppose we have an Angular service method getBooks() that returns a list of books from a Web API.
The first method is the RxJS subscribe method, where we return an Observable type as shown:
getBooks(): Observable<Book[]> {
let books: Books[] = …
..
..
return of(books);
}
To obtain results from the above method we use the following subscribe call:
this.api.getBooks().subscribe((res) => {
// process book list from the res variable.
…
console.log('number of books = ' + res.length);
});
The equivalent call using async await JavaScript keywords for calling to asynchronous services starts with a function within our Angular service. In the function we prefix the function with the async keyword. The return is a call to the static Promise resolve() method:
async getBooks(): Promise<Books[]> {
let books: Book[] = …
..
..
return await Promise.resolve(books);
}
The resolve() method resolves the API call with a value, which is an array of Books.
The equivalent function using the RxJS of operator is shown below:
getBooks(): Observable<Book[]> {
let books: Books[] = …
..
..
return of(books);
}
To obtain results from the above method with the resolve() method, we use the following promise then() call:
this.api.getBooks().then((res) => {
// process book list from the res variable.
…
console.log('number of books = ' + res.length);
});
We can also chain the catch() method to intercept errors from the service call:
this.api.getBooks().then((res) => {
// process book list from the res variable.
…
console.log('number of books = ' + res.length);
})
.catch(err => {
console.log('the error returned is : ' + err);
});
As we can see, you have at least two methods of dealing with asynchronous service calls within an Angular application.
Where the application is from an earlier version of Angular and JavaScript, the use of promises would have been the most common way of dealing with asynchronous calls to services. With the RxJS libraries, which have been available to modern browsers since October 2013, this has made dealing with and writing asynchronous calls more straightforward and manageable.
Since the release of ECMA script in June 2017 we have an additional choice of dealing with handling asynchronous calls using the async await pattern.
If you are a developer who is using earlier AngularJS 1.x code, then continuing to use Promises would be recommended until the code base can be converted to using ECMA 2017 compliant async await.
If you are a developer who uses Angular 4.x and beyond, then using RxJS to implement asynchronous programming tasks is recommended as the library is quite stable and has a very wide adoption in the developer community.
That is all for today’s post.
I hope you have found this post useful and informative.
Andrew Halil is a blogger, author and software developer with expertise of many areas in the information technology industry including full-stack web and native cloud based development, test driven development and Devops.