angularhttprequestdata-sharing

sharing the async data without interrupting the http request


I have two pages that one can navigate from one to another and each of those pages making the same http request, completely the same request. Obviously, I don't want to make the same request over and over again on navigating between 2 pages, so i store the response of the request in my service after the first time request is made and finished. But the shortcoming is that the http request sometimes takes up to 5-6 seconds to finish, so if the user navigates to the other page when the request has not finished, request is made again. For example, two pages are page1 and page2. User goes to page1, http request is made, user waits for 4 seconds but request is not finished and user goes to page2 and request is made again and user has to wait 5 more seconds to see the result. I want the http request to not be interrupted between 2 pages. How do i solve this?


Solution

  • I think this would be a good opportunity for a Subject. Here is some code that would do the trick, and I'll explain it below.

    @Injectable()
    export class ClaimsService {
    
        private _claimsSubject = new Subject<any>(); // what every request will return
        private _requestIsInProgress = false; // determines if a request is being made
    
        constructor(private http: HttpClient) {}
    
        public getClaims(): Observable<any> {
            // check if we have a request in progress or need to make one
            if (!this._requestIsInProgress) {
                this._requestIsInProgress = true;
                // make the request
                this.http.get<any>('your apis url to get the claims')
                    .subscribe((claims) => {
                        this._requestIsInProgress = false; // request is complete
                        this._claimsSubject.next(claims); // emit the data
                    });
            }
    
            return this._claimsSubject.asObservable(); // this is returning an observable that needs to be unsubscribed from
        }
    }
    

    In this service, you have a method that always returns a Subject. That Subject will emit the data once the call is completed. If you come into the call and there is no request being made, than we set one up and use a boolean flag to say that a request is in progress. When that request is completed, it will emit the result from the subject.

    Either way, the call always returns that same subject.

    So in your example, someone is on page 1, they ask for the claims and they get the subject and a request is fired, but it hasn't resolved as of yet. They navigate away and the request is still going, and the second page now asks for the same thing. That request is already in progress so they are just sent the subject. The request finally completes, and they get the result.

    NOTE: the only thing wrong with this, is that you are returning a Subject which doesn't complete like an http call would. So you have to save that subscription and unsubscribe from it. https://brianflove.com/2016/12/11/anguar-2-unsubscribe-observables/