# Use cases for the Aurelia HttpClient

**URL:** <https://discourse.aurelia.io/t/use-cases-for-the-aurelia-httpclient/1928>\
**Category:** Framework Knowledge\
**Created:** [November 21, 2018, 7:44pm UTC](https://discourse.aurelia.io/t/use-cases-for-the-aurelia-httpclient/1928 "2018-11-21T19:44:26Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![sean.hunter.aus](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/sean.hunter.aus/32/17_2.png) [@sean.hunter.aus](https://discourse.aurelia.io/u/sean.hunter.aus)\
**Post date:** [November 21, 2018, 7:44pm UTC](https://discourse.aurelia.io/t/use-cases-for-the-aurelia-httpclient/1928/1 "2018-11-21T19:44:26Z")

</div>

One of Aurelia’s strengths is the way that it provides a set of well-designed building blocks that you can use in a variety of different ways. One of these building blocks is the `HttpClient`, a wrapper for the browsers [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) which is a modern replacement for the old `XMLHttpRequest` object.

This morning I was looking for a way to show loading progress in a simple and consistent way across a new application I’m building. The goal was to give the user some kind of visual feedback any time I was making an Http request. Looking around I found the [nprogress](http://ricostacruz.com/nprogress/) library, which does a great job of showing a slim progress bar in a way similar to apps like Youtube.

Hooking this up was simple:

`npm install nprogress --save`

Import the styles at the top of my `app.ts`:

`import 'nprogress/nprogress.css';`

Then, in my application, I set the `HttpClient` up with an interceptor to automatically add some required headers to each request. Interceptors are one of those powerful features that buy you a great amount of flexibility when using the `HttpClient`. So, I decided to modify my interceptor slightly to also report progress via `nprogress`.

First I needed to import the module:

`import * as nprogress from 'nprogress';`

From there it was a simple matter of modifying my intercepter to report progress on the start and end of each request:

```
    get interceptor(){
        return {
            request(request) {
                nprogress.start() //report loading started
                request.headers.append('appId', this.state.appId);
                return request; 
            },
            response(response) {
              nprogress.done() //report loading finished
              return response;
            }
        };
    }

```

This took me only a few minutes to wire up, but is working nicely. It got me thinking, there are probably many other novel use cases for the various features of Aurelia’s Fetch client and HttpClient, interceptors, and more. I’d be interested to see examples of what other’s are doing.

**Edit** :

As @huochunpeng quite rightly points out, there is another feature of the `HttpClient` which makes this even simpler. The `HttpClient` has an `isRequesting` [property](https://aurelia.io/docs/api/fetch-client/class/HttpClient/property/isRequesting/) to maintain the state of when requests are being made. So, a more elegant way to implement this logic is to create a custom element, like the loading indicator from the app contacts sample [https://github.com/aurelia/app-contacts/blob/master/src/resources/elements/loading-indicator.js](https://github.com/aurelia/app-contacts/blob/master/src/resources/elements/loading-indicator.js).

```
import * as nprogress from 'nprogress';
import {bindable, noView} from 'aurelia-framework';

@noView()
export class LoadingIndicator {
  @bindable loading = false;

  loadingChanged(newValue){
    if(newValue){
      nprogress.start();
    }else{
      nprogress.done();
    }
  }
}

```

This element is then included in the top of your page, and can be used to trigger `nprogress` as follows:

```
  <loading-indicator loading.bind="router.isNavigating || http.isRequesting"></loading-indicator>
```

---

<div class="post-metadata">

**Author:** ![Stuart](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/stuart/32/664_2.png) [@Stuart](https://discourse.aurelia.io/u/Stuart)\
**Post date:** [November 21, 2018, 8:09pm UTC](https://discourse.aurelia.io/t/use-cases-for-the-aurelia-httpclient/1928/2 "2018-11-21T20:09:43Z")

</div>

Great work Sean - just something that you might like to consider:  
#1 if there is more than one concurrent request, then the first response will mark the progress as finished, even though others are still waiting. You could perhaps increment a counter on each request, then decrement on each response, and set the progress as done only when the counter is 0.  
#2 do you happen to know if the response callback occurs when there is a timeout on the HttpClient?

---

<div class="post-metadata">

**Author:** ![sean.hunter.aus](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/sean.hunter.aus/32/17_2.png) [@sean.hunter.aus](https://discourse.aurelia.io/u/sean.hunter.aus)\
**Post date:** [November 21, 2018, 8:19pm UTC](https://discourse.aurelia.io/t/use-cases-for-the-aurelia-httpclient/1928/3 "2018-11-21T20:19:55Z")

</div>

Thanks @Stuart, that’s a great point actually. I should have thought about subsequent requests. Will play with this a bit today to get it working in different scenarios and update the sample. Good question on the response callback. I’ll do some testing on this and update the thread 😄

---

<div class="post-metadata">

**Author:** ![huochunpeng](https://avatars.discourse-cdn.com/v4/letter/h/49beb7/32.png) [@huochunpeng](https://discourse.aurelia.io/u/huochunpeng)\
**Post date:** [November 21, 2018, 8:26pm UTC](https://discourse.aurelia.io/t/use-cases-for-the-aurelia-httpclient/1928/4 "2018-11-21T20:26:41Z")

</div>

It’s actually in contact manager tutorial.

[https://aurelia.io/docs/tutorials/creating-a-contact-manager#adding-a-loading-indicator](https://aurelia.io/docs/tutorials/creating-a-contact-manager#adding-a-loading-indicator)

Using binding is easier than your manual approach.

```auto
<loading-indicator loading.bind="router.isNavigating || api.isRequesting"></loading-indicator>

```

Furthermore, using binding you can do trick like this [Tip: show spinner only when something is slow](https://discourse.aurelia.io/t/tip-show-spinner-only-when-something-is-slow/967)

```auto
<loading-indicator loading.bind="router.isNavigating || api.isRequesting & debounce"></loading-indicator>

```

---

<div class="post-metadata">

**Author:** ![zewa666](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/zewa666/32/19_2.png) [@zewa666](https://discourse.aurelia.io/u/zewa666)\
**Post date:** [November 21, 2018, 8:49pm UTC](https://discourse.aurelia.io/t/use-cases-for-the-aurelia-httpclient/1928/5 "2018-11-21T20:49:31Z")

</div>

Another good use case for the interceptor is to create stubs for Rest endpoints which arent yet available. E.g your Backend Team hasnt yet released a new feature but you’d still like to finish the Frontend part. Once the new routes are available simple disable the interceptor and rock on

---

<div class="post-metadata">

**Author:** ![sean.hunter.aus](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/sean.hunter.aus/32/17_2.png) [@sean.hunter.aus](https://discourse.aurelia.io/u/sean.hunter.aus)\
**Post date:** [November 21, 2018, 9:12pm UTC](https://discourse.aurelia.io/t/use-cases-for-the-aurelia-httpclient/1928/6 "2018-11-21T21:12:57Z")

</div>

That’s a nice point as well. Good that it hooks in for both the `requesting` and `navigating` cases. The thing I appreciate the most about the `contact-manager` manager approach of using a `requesting` variable is that the reporter of this state doesn’t need to know about `nprogress`. On the flip side, the benefit I see of attaching this logic to the Http interceptor instead of inlining it in the service class calls is that you only need to specify it once. In the contact manager, each web API method needs to explicitly specify whether the app is making a request.

From the tutorial:

```
 getContactDetails(id){
    this.isRequesting = true; 
    return new Promise(resolve => {
     ...
  }

  saveContact(contact){
    this.isRequesting = true;
    ...
}

```

So even though binding is convenient in some ways, we still have a manual approach for reporting that we’re `requesting`.

Perhaps a hybrid approach would work best, where the app set a `requesting` state for the app when there the request count was greater than or equal to 1.

---

<div class="post-metadata">

**Author:** ![sean.hunter.aus](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/sean.hunter.aus/32/17_2.png) [@sean.hunter.aus](https://discourse.aurelia.io/u/sean.hunter.aus)\
**Post date:** [November 21, 2018, 9:15pm UTC](https://discourse.aurelia.io/t/use-cases-for-the-aurelia-httpclient/1928/7 "2018-11-21T21:15:35Z")

</div>

That’s a great suggestion actually, typically we just stub these out on the [asp.net](http://asp.net) core web api side, but this approach would obviate the need for that entirely.

---

<div class="post-metadata">

**Author:** ![huochunpeng](https://avatars.discourse-cdn.com/v4/letter/h/49beb7/32.png) [@huochunpeng](https://discourse.aurelia.io/u/huochunpeng)\
**Post date:** [November 21, 2018, 9:25pm UTC](https://discourse.aurelia.io/t/use-cases-for-the-aurelia-httpclient/1928/8 "2018-11-21T21:25:06Z")

</div>

You don’t need to manually set isRequesting, it’s a observable property on aurelia-http-client itself, same as the observable property isNavigating on the router itself.

[https://aurelia.io/docs/api/fetch-client/class/HttpClient/property/isRequesting](https://aurelia.io/docs/api/fetch-client/class/HttpClient/property/isRequesting)

---

<div class="post-metadata">

**Author:** ![sean.hunter.aus](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/sean.hunter.aus/32/17_2.png) [@sean.hunter.aus](https://discourse.aurelia.io/u/sean.hunter.aus)\
**Post date:** [November 21, 2018, 9:26pm UTC](https://discourse.aurelia.io/t/use-cases-for-the-aurelia-httpclient/1928/9 "2018-11-21T21:26:08Z")

</div>

Ah very nice, that certainly simplifies things! So in the contact manager tutorial, we only manually set the requesting state because we’re not actually using the `HttpClient` to make the request (it’s just stubbed out using `Promise.Resolve` for demo purposes.

---

<div class="post-metadata">

**Author:** ![huochunpeng](https://avatars.discourse-cdn.com/v4/letter/h/49beb7/32.png) [@huochunpeng](https://discourse.aurelia.io/u/huochunpeng)\
**Post date:** [November 21, 2018, 9:28pm UTC](https://discourse.aurelia.io/t/use-cases-for-the-aurelia-httpclient/1928/10 "2018-11-21T21:28:43Z")

</div>

> [@sean.hunter.aus](#):
>
> we only manually set the requesting state

Which line in the tutorial are you talking about?

---

<div class="post-metadata">

**Author:** ![sean.hunter.aus](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/sean.hunter.aus/32/17_2.png) [@sean.hunter.aus](https://discourse.aurelia.io/u/sean.hunter.aus)\
**Post date:** [November 21, 2018, 9:45pm UTC](https://discourse.aurelia.io/t/use-cases-for-the-aurelia-httpclient/1928/11 "2018-11-21T21:45:23Z")

</div>

The contact manager tutorial [https://github.com/aurelia/app-contacts](https://github.com/aurelia/app-contacts). What I mean is that the requests are faked at the back end rather than using the `HttpClient` [https://github.com/aurelia/app-contacts/blob/master/src/web-api.js](https://github.com/aurelia/app-contacts/blob/master/src/web-api.js).

---

<div class="post-metadata">

**Author:** ![huochunpeng](https://avatars.discourse-cdn.com/v4/letter/h/49beb7/32.png) [@huochunpeng](https://discourse.aurelia.io/u/huochunpeng)\
**Post date:** [November 21, 2018, 9:57pm UTC](https://discourse.aurelia.io/t/use-cases-for-the-aurelia-httpclient/1928/12 "2018-11-21T21:57:50Z")

</div>

ok, got it, because it’s a fake in-memory api, trying to mimic http-client. When you use real aurelia-http-client, you don’t need that.

---

<div class="post-metadata">

**Author:** ![justindra](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/justindra/32/175_2.png) [@justindra](https://discourse.aurelia.io/u/justindra)\
**Post date:** [November 27, 2018, 9:17pm UTC](https://discourse.aurelia.io/t/use-cases-for-the-aurelia-httpclient/1928/13 "2018-11-27T21:17:52Z")

</div>

That’s cool. Never realized that `aurelia-fetch-client` had the `isRequesting` flag.

We use `aurelia-fetch-client` extensively to add special headers for Auth purposes as well as to return a more User friendly error messages when there are errors instead of returning what the backend returns which may be more developer-friendly rather than user-friendly.

We also reject calls before we even make the request if there are things missing, e.g. POST requests with no body. Or if the user is not currently logged in yet, we reject it unless it is a public endpoint. This saves a lot of requests to the backend which we know will be rejected anyways.

---

<div class="post-metadata">

**Author:** ![sean.hunter.aus](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/sean.hunter.aus/32/17_2.png) [@sean.hunter.aus](https://discourse.aurelia.io/u/sean.hunter.aus)\
**Post date:** [November 27, 2018, 9:35pm UTC](https://discourse.aurelia.io/t/use-cases-for-the-aurelia-httpclient/1928/14 "2018-11-27T21:35:04Z")

</div>

Nice, I particularly like the ideas for intercepting the error responses to return clean error messages, and optimising HTTP traffic by avoiding unnecessary calls to private APIs. I actually never thought of using it that way but it makes a lot of sense. 👍

---

<div class="post-metadata">

**Author:** ![huochunpeng](https://avatars.discourse-cdn.com/v4/letter/h/49beb7/32.png) [@huochunpeng](https://discourse.aurelia.io/u/huochunpeng)\
**Post date:** [November 27, 2018, 9:39pm UTC](https://discourse.aurelia.io/t/use-cases-for-the-aurelia-httpclient/1928/15 "2018-11-27T21:39:59Z")

</div>

@justindra for a layer between backend endpoints and frontend, there is [service worker](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API) API specifically designed for this kind of work. You may want to investigate that, it got lots to offer, but [doesn’t support IE](https://caniuse.com/#search=service%20worker).

---

<div class="post-metadata">

**Author:** ![justindra](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/justindra/32/175_2.png) [@justindra](https://discourse.aurelia.io/u/justindra)\
**Post date:** [November 27, 2018, 10:59pm UTC](https://discourse.aurelia.io/t/use-cases-for-the-aurelia-httpclient/1928/16 "2018-11-27T22:59:28Z")

</div>

@huochunpeng literally the only reason we haven’t used that is the need to support IE. But once we can drop that support for IE definitely will use it.

---

<div class="post-metadata">

**Author:** ![ben-girardet](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/ben-girardet/32/333_2.png) [@ben-girardet](https://discourse.aurelia.io/u/ben-girardet)\
**Post date:** [January 11, 2019, 11:28am UTC](https://discourse.aurelia.io/t/use-cases-for-the-aurelia-httpclient/1928/17 "2019-01-11T11:28:16Z")

</div>

I didn’t know about the `isRequesting` observable and started to use it now with great joy. Very helpful to provide user feedback on requests in progress.

I’m facing a situation which I don’t know if it’s a bug or else. When I use the fetch-client to make a request towards an API that is not reachable, the fetch-client rejects the call with a “Failed to fetch” error but the `isRequesting` property stays true. Is this normal behavior?

I’ve opened an issue on fetch-client repo is that can be of any help:

> <https://github.com/aurelia/fetch-client/issues/119>

---

<div class="post-metadata">

**Author:** ![Alfhir](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/alfhir/32/1510_2.png) [@Alfhir](https://discourse.aurelia.io/u/Alfhir)\
**Post date:** [September 27, 2019, 12:26pm UTC](https://discourse.aurelia.io/t/use-cases-for-the-aurelia-httpclient/1928/18 "2019-09-27T12:26:56Z")

</div>

Hi Ben,

i think it was an issue with fetch-client: [https://github.com/aurelia/fetch-client/issues/119](https://github.com/aurelia/fetch-client/issues/119)  
v1.8 fixed it.

Best
