user2810022
user2810022

Reputation: 31

Angular 2 - Avoid delay when chaining http request

    this.http.get(validate\uniqueness).subscribe(unique => {
        console.log(" first subscribe ");
        if(unique.isValid) {
            this.http.put(url, data).subscribe(val => {
            console.log("second Subscribe")
            }
        });
    });

We have a custom http spinner that starts when request is pending and stops when response is received. In the above code on first subscribe call the spinner gets invoked and the spinner stops as soon as the result is retrieved and page is displayed without the spinner and on invoking the 2nd subscribe again the spinner is invoked. We could some delay between first call and second call.. Is there a way to avoid the delay? I have used mergeMap, flatMap but no luck.

Upvotes: 0

Views: 547

Answers (1)

Giora Guttsait
Giora Guttsait

Reputation: 1300

First of all, you should chain your http calls:

this.http.get(validate\uniqueness)
    .map(req => req.json().unique)
    .filter(unique => unique.isValid)
    .switchMap(this.http.put(....))
    .subscribe(val => console.log(val))

But that ain't gonna solve your issue either. You have two separate http requests here, one that is triggered by another. You're always going to have some delay between those requests. You can probably add a delay before the spinner stops, allowing subsequent requests to "ride" the same spinner.

What I have done for loading indication is write my own rxjs operators.

Basically, my http calls look like this:

Observable.loadingDefer('name of loading state', () => {
    // log or whatever
    return this.http.get(...)
})
.map(...)
...
.stopLoading('name of loading state')
.subscribe(...)

I have a simple service that saves a Map<string, BehaviourSubject<boolean>>, which is basically a map between the name of a loading state (in case I want to affect different objects, and not have one global loading state), and a behavior subject that indicates whether it is loading or not, defaulting at false.

Observable.loadingDefer uses Observable.defer, except it uses the service (which is exported as sort of a singleton, much like angular-redux's NgRedux) and states a loading state.

The stopLoading operator uses the finally operator to send the stop sign for the indication. I used finally here to address cases where requests fail.

This is good enough for me, but I assume it does make a bit of boilerplate around each http call. Perhaps this is avoidable.

Hope it helps you somehow :)

Upvotes: 1

Related Questions