4

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 ..

  • A Angular subscription issue
  • A httpclient bug
  • A problem at the server end (hard to imagine that)

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.

user2808054
  • 1,376
  • 1
  • 11
  • 19

1 Answers1

1

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.

Alex
  • 274
  • 3
  • 12
  • Thanks loads for the the response, but as I understand it this will effectively cancel the triggered event whhen some 'older' http requests finish. As this happens with differeing URLs as well, it would end up not reacting to (for example) a save completing if it took longer than some other request in the meantime. Am I right in thnking that ? – user2808054 Nov 24 '17 at 13:43
  • Sorry I wasn't clear enough, switch map will cancel all older subscriptions from the observable you are using it on, so that won't happen for different URLs. Even if you are using switchmap on multiple requests, each switchmap will cancel it's own requests and will not interfere with other requests. – Alex Nov 24 '17 at 13:50
  • @Alex, please update your answer. Otherwise it's going to be deleted. – derloopkat Nov 24 '17 at 21:31
  • @Alex ah yes I see, thanks for the update. I've upvoted but will wait to see if anyone else replies. I think that is kind of a workaround rather than a fix ? It seems really bizarre behaviour for the responses from two separate requests to be mingled, even from two different URLs. (why would that ever be desirable?) I have the feeling I must be missing something fundamental if this is possible, even with .map(). any thoughts? – user2808054 Nov 30 '17 at 14:09