I have written an app in Angular 4. And it looks like angular makes 2 requests each time I try to access an API. This happens for all methods across my app including; GET, DELETE, PUT, POST
I will add some code sample below. For example I have a NotificationComponent that lists a ll notifications from the database. The NotificationComponent has a method which loads the notifications on ngOnInit
;
this.NotificationService.All(AdditionalParams)
.subscribe(
notifications => {
this.AllNotifications.Notifications = notifications.data;
this.AllNotifications.Data = notifications;
this.AllNotifications.Loading = false;
this.AllNotifications.Loaded = true;
this.AllNotifications.HasRequestError = false;
},
(error)=> {
this.AllNotifications.Loading = false;
this.AllNotifications.Loaded = false;
this.AllNotifications.RequestStatus = error.status;
if (typeof error.json == 'function' && error.status!=0) {
let errorObject = error.json();
this.AllNotifications.RequestError = errorObject;
} else {
this.AllNotifications.RequestError = "net::ERR_CONNECTION_REFUSED";
}
this.AllNotifications.HasRequestError = true;
});
}
The method subscribes to the All method found in the NotificationService. The All method looks like this;
All(AdditionalParams: object): Observable<any> {
let options = new RequestOptions({ headers: this.headers });
let params = new URLSearchParams();
//params.set("token", this.authenticationService.token);
for (var key in AdditionalParams) {
params.set(key, AdditionalParams[key]);
}
options.params = params;
return this.http.get(this.notificationsUrl, options)
.map(response => response.json())
.catch(this.handleError);
}
Somehow the request is sent twice. I think this in my console log;
XHR finished loading: GET "[REMOVED]/notifications?page=1&event=1&token=eyJ0eXAiOi…GkiOiJ1bGYxSnJPa1Zya0M2NmxDIn0.3kA8Pd-tmOo4jUinJqcDeUy7mDPdgWpZkqd3tbs2c8A"
XHR finished loading: GET "[REMOVED]/notifications?page=1&event=1&token=eyJ0eXAiOi…GkiOiJ1bGYxSnJPa1Zya0M2NmxDIn0.3kA8Pd-tmOo4jUinJqcDeUy7mDPdgWpZkqd3tbs2c8A"
About 3 seconds apart.
I have a service called "AuthenticationService". In this service I have added an http interceptor using ng-http-interceptor. The http interceptor gets added to all requests. And it looks like this;
httpInterceptor.request().addInterceptor((data, method) => {
console.log ("Before httpInterceptor: ", data);
var RequestOptionsIndex = null;
for (var _i = 0; _i < data.length; _i++) {
if (typeof data[_i] == 'object' && data[_i].hasOwnProperty('headers')){
RequestOptionsIndex = _i;
}
}
if (RequestOptionsIndex == null) {
let options = new RequestOptions({headers: new Headers({'Content-Type': 'application/json'})});
let params = new URLSearchParams();
data.push(options);
RequestOptionsIndex = data.length-1;
}
//console.log (data, this.loginURL, 'RequestOptionsIndex: ', RequestOptionsIndex);
if (!data[RequestOptionsIndex].hasOwnProperty('headers')){
data[RequestOptionsIndex].headers = new Headers({'Content-Type': 'application/json'});
}
if (data[0]!=this.loginURL && (data[RequestOptionsIndex].headers.get('Authorization')=="" || data[RequestOptionsIndex].headers.get('Authorization')==null)) {
data[RequestOptionsIndex].headers.append("Authorization", 'Bearer ' + this.token);
}
if (data[RequestOptionsIndex].params!=undefined && data[RequestOptionsIndex].params!=null) {
data[RequestOptionsIndex].params.set('token', this.token);
}else {
let params = new URLSearchParams();
params.set('token', this.token);
data[RequestOptionsIndex].params = params;
}
console.log ("httpInterceptor data", data, ": RequestOptionsIndex", RequestOptionsIndex);
return data;
});
httpInterceptor.response().addInterceptor((res, method) => {
res.map(response => response.json())
.catch((err: Response, caught: Observable<any>) => {
if (err.status === 401) {
this.logout();
this.router.navigate(["/login"]);
location.reload();
return Observable.throw("401 Unauthorized");
}
return Observable.throw(caught); // <-----
}).subscribe()
return res;
});
I have written an app in Angular 4. And it looks like angular makes 2 requests each time I try to access an API. This happens for all methods across my app including; GET, DELETE, PUT, POST
I will add some code sample below. For example I have a NotificationComponent that lists a ll notifications from the database. The NotificationComponent has a method which loads the notifications on ngOnInit
;
this.NotificationService.All(AdditionalParams)
.subscribe(
notifications => {
this.AllNotifications.Notifications = notifications.data;
this.AllNotifications.Data = notifications;
this.AllNotifications.Loading = false;
this.AllNotifications.Loaded = true;
this.AllNotifications.HasRequestError = false;
},
(error)=> {
this.AllNotifications.Loading = false;
this.AllNotifications.Loaded = false;
this.AllNotifications.RequestStatus = error.status;
if (typeof error.json == 'function' && error.status!=0) {
let errorObject = error.json();
this.AllNotifications.RequestError = errorObject;
} else {
this.AllNotifications.RequestError = "net::ERR_CONNECTION_REFUSED";
}
this.AllNotifications.HasRequestError = true;
});
}
The method subscribes to the All method found in the NotificationService. The All method looks like this;
All(AdditionalParams: object): Observable<any> {
let options = new RequestOptions({ headers: this.headers });
let params = new URLSearchParams();
//params.set("token", this.authenticationService.token);
for (var key in AdditionalParams) {
params.set(key, AdditionalParams[key]);
}
options.params = params;
return this.http.get(this.notificationsUrl, options)
.map(response => response.json())
.catch(this.handleError);
}
Somehow the request is sent twice. I think this in my console log;
XHR finished loading: GET "[REMOVED]/notifications?page=1&event=1&token=eyJ0eXAiOi…GkiOiJ1bGYxSnJPa1Zya0M2NmxDIn0.3kA8Pd-tmOo4jUinJqcDeUy7mDPdgWpZkqd3tbs2c8A"
XHR finished loading: GET "[REMOVED]/notifications?page=1&event=1&token=eyJ0eXAiOi…GkiOiJ1bGYxSnJPa1Zya0M2NmxDIn0.3kA8Pd-tmOo4jUinJqcDeUy7mDPdgWpZkqd3tbs2c8A"
About 3 seconds apart.
I have a service called "AuthenticationService". In this service I have added an http interceptor using ng-http-interceptor. The http interceptor gets added to all requests. And it looks like this;
httpInterceptor.request().addInterceptor((data, method) => {
console.log ("Before httpInterceptor: ", data);
var RequestOptionsIndex = null;
for (var _i = 0; _i < data.length; _i++) {
if (typeof data[_i] == 'object' && data[_i].hasOwnProperty('headers')){
RequestOptionsIndex = _i;
}
}
if (RequestOptionsIndex == null) {
let options = new RequestOptions({headers: new Headers({'Content-Type': 'application/json'})});
let params = new URLSearchParams();
data.push(options);
RequestOptionsIndex = data.length-1;
}
//console.log (data, this.loginURL, 'RequestOptionsIndex: ', RequestOptionsIndex);
if (!data[RequestOptionsIndex].hasOwnProperty('headers')){
data[RequestOptionsIndex].headers = new Headers({'Content-Type': 'application/json'});
}
if (data[0]!=this.loginURL && (data[RequestOptionsIndex].headers.get('Authorization')=="" || data[RequestOptionsIndex].headers.get('Authorization')==null)) {
data[RequestOptionsIndex].headers.append("Authorization", 'Bearer ' + this.token);
}
if (data[RequestOptionsIndex].params!=undefined && data[RequestOptionsIndex].params!=null) {
data[RequestOptionsIndex].params.set('token', this.token);
}else {
let params = new URLSearchParams();
params.set('token', this.token);
data[RequestOptionsIndex].params = params;
}
console.log ("httpInterceptor data", data, ": RequestOptionsIndex", RequestOptionsIndex);
return data;
});
httpInterceptor.response().addInterceptor((res, method) => {
res.map(response => response.json())
.catch((err: Response, caught: Observable<any>) => {
if (err.status === 401) {
this.logout();
this.router.navigate(["/login"]);
location.reload();
return Observable.throw("401 Unauthorized");
}
return Observable.throw(caught); // <-----
}).subscribe()
return res;
});
Share
Improve this question
asked Aug 6, 2017 at 17:05
user5500750user5500750
1 Answer
Reset to default 13While posting the question I noticed that I was subscribing to the response in my httpInterceptor.response().addInterceptor
Removing .subscribe()
fixes it. So it bees;
httpInterceptor.response().addInterceptor((res, method) => {
return res.map(response => response) // => response.json()
.catch((err: Response, caught: Observable<any>) => {
if (err.status === 401) {
this.logout();
this.router.navigate(["/login"]);
location.reload();
return Observable.throw("401 Unauthorized");
}
return Observable.throw(caught); // <-----
})//.share().subscribe()
//return res;
});
Just in case someone makes a silly mistake like this. This was my solution.
The problem happens when you subscribe to a request more than once, so it gets executed multiple times. The solution is to share the request or subscribe to it once. I am not sure about the exact way to share a request multiple subscriptions without reloading hopefully someone will confirm this. I tried .share().subscribe()
but didn't seem to work for me.