user2808054
user2808054

Reputation: 1386

Angular 4 http responses are mixed together

I am using Angular 4. This issue has been found in safari, chrome and Firefox.

My Angular 4 application sends XHR Requests using httpclient to a REST service. Communication is in JSON.

There's potential CORS issue so the browser sends a pre-flight OPTIONS request.

The request returns user's details in JSON.

Sometimes (maybe one in 5), I see the responses combined:

eg if two requests are sent in quick successtion (same URL), I see this: OPtions Request sent Options Request sent GET Request sent (no response) GET request sent (Results combined with last GET returned)

So for the last GET, I would receive :

    {"username":"Dave Smith","badge":"12345", "lockPollTime":61000}{"username":"Dave Smith","badge":"12345", "lockPollTime":61000}

(that is: two JSON objects co-joined, which is a JSON syntax error so the app breaks) .. whereas I would expect the two GETs to receive one of these each:

{"username":"Dave Smith","badge":"12345", "lockPollTime":61000}

I see this with other requests too, twhere the URL differs (same server & REST service, different operatons).

The call to get the login info is like this from an authService service:

login(username: string, password: string): Observable<LoginResponse|boolean> {
    return this.http.get(ApiRoutes.auth.login, this.loginHeaders(username, password)).map((response: Response) => {
        if(response.headers.get('Content-Type').indexOf('text/html') !== -1) {
            return false;
        }

        return new LoginResponse(response);
    });
}

And the call to it is like this:

this.authService.login(username, password).subscribe(
    (user: LoginResponse|boolean) => { .. etc etc } )

User credentials are provided via a n Interceptor:

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if(this.authService.getAuthToken()) {
        request = request.clone({
            setHeaders: {
                Authorization: `Basic ${this.authService.getAuthToken()}`
            }
        });
    }

    return next.handle(request);
}

If I try one of the REST service URLs in a browser window and hit F5 many times, I can't reproduce the problem. Seems to be only angular http requests, although I don't know whether that's a fair test.

I'm not sure whether this is ..

If anyone can shed any light on this, I'll be very grateful and will roam the streets chanting your userID through a loudhailer.

The only clue I have is that sometimes asynchronous requests are sent (eg a heartbeat 'ping') and these sometimes seem to clash with a user-initiated request (eg a save, using a POST request or a GET to grab some other info).

Any help or advice gratefully received.

Upvotes: 4

Views: 688

Answers (1)

Alex
Alex

Reputation: 274

Simply replace map with switchmap and it will automatically cancel all requests except the last one.

More info: Search with switchmap

Edit: For example if you have 2 different functions

     http.get(API_URL1).switchmap(...)
     http.get(API_URL2).map(...) 

the switchmap can cancel only older requests coming from API_URL1. Or even if you have something like this:

     http.get(API_URL1).switchmap(...)
     http.get(API_URL2).switchmap(...)

Having requests from URL1 and URL2 at the same time is fine, as each switchmap can only cancel older requests from its URL.

Hope this clears your confusion.

Upvotes: 1

Related Questions