Reputation: 1386
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
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