Reputation: 4096
I trying to put a progress bar in my http call but some how i wont be able to make a sync HTTP call request instead its going in async fashion.
below is function for making http call
public authenticationt2cHTTP(email, password) {
console.log("authenticationt2cHTTP WITH HEADERS");
const body = new HttpParams()
.set('email', email)
.set('password', password);
const req = new HttpRequest('POST', 'http://192.168.0.135:8080/rest/auth/login', body, {
reportProgress: true,
headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded')
});
this.http.request(req).subscribe(event => {
// Via this API, you get access to the raw event stream.
// Look for upload progress events.
if (event.type === HttpEventType.UploadProgress) {
// This is an upload progress event. Compute and show the % done:
const percentDone = Math.round(100 * event.loaded / event.total);
console.log(`File is ${percentDone}% uploaded.`);
} else if (event instanceof HttpResponse) {
console.log('File is completely uploaded!');
}
});
}
below is code which i am using in my component class for making a call and showload is temp variable for showing/hiding preloader of the page.
this.showLoader = false;
var k = this.myhttpService.authenticationt2c(this.form.get("email").value, this.form.get("password").value);
this.showLoader = true;
Upvotes: 5
Views: 7708
Reputation: 73357
As mentioned in comments, this is asynchronous, so while the request takes some time to execute,
this.showLoader = false;
// takes some time to execute
var k = this.myhttpService.authenticationt2c(...);
// executed while waiting for above code to execute
this.showLoader = true;
Instead, from your service, return an Observable and in component subscribe. Then inside the callback (subscribe) switch the boolean flag. I'd guess that you would want to actually switch the boolean flag showLoader
to false
after the request have been completed, so I switched them around below:
this.showLoader = true;
this.myhttpService.authenticationt2c(...)
.subscribe(() => this.showLoader = false)
and from the service, as said, return an Observable, so use map
instead of subscribe
:
this.http.request(req).map(event => { ... })
Check these links for reading up on asynchronicity: How do I return the response from an Observable/http/async call in angular2? and How do I return the response from an asynchronous call?
Upvotes: 2
Reputation: 3976
I use the following http
service wrapper to get access to different hooks like handleResponse
, beforeRequest
, afterResponse
, onCatch
& onSuccess
.
The API services should consume the HttpInterceptor
wrapper (which internally triggers the http call and gives access to above mentioned hooks).
Note how the loader logic is implemented in beforeRequest
& afterResponse
hooks.
import { Injectable } from "@angular/core";
import { XHRBackend, RequestOptions, Request, RequestOptionsArgs, Response, Http, Headers } from "@angular/http";
import { Store } from "@ngrx/store";
import { Observable } from "rxjs/Rx";
import { Observer } from "rxjs/Observer";
import { Response as ApiResponse } from "../../models/base/response.model";
import { ToastModel } from "../../redux/app-reducers";
import { ReducerActions } from "../../redux/reducer-actions";
@Injectable()
export class HttpInterceptor extends Http {
constructor(private _XHRBackend: XHRBackend,
private _RequestOptions: RequestOptions,
private _ToastStore: Store<ToastModel>,
private _LoaderStore: Store<boolean>) {
super(_XHRBackend, _RequestOptions);
}
public request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
return this.handleResponse(super.request(url, options));
}
public get(url: string, options?: RequestOptionsArgs): Observable<Response> {
this.beforeRequest(url);
return super.get(url, this.getRequestOptionArgs(options));
}
public post(url: string, body: any, options?: RequestOptionsArgs): Observable<Response> {
this.beforeRequest(url, body);
return super.post(url, body, this.getRequestOptionArgs(options));
}
public put(url: string, body: any, options?: RequestOptionsArgs): Observable<Response> {
this.beforeRequest(url, body);
return super.put(url, body, this.getRequestOptionArgs(options));
}
public delete(url: string, options?: RequestOptionsArgs): Observable<Response> {
this.beforeRequest(url);
return super.delete(url, this.getRequestOptionArgs(options));
}
private getRequestOptionArgs(options?: RequestOptionsArgs): RequestOptionsArgs {
if (options == null) {
options = new RequestOptions();
}
if (options.headers == null) {
options.headers = new Headers();
}
options.headers.append('Content-Type', 'application/json');
return options;
}
private handleResponse(response: Observable<Response>): Observable<Response> {
return response
.catch(this.onCatch)
.do(this.onSuccess.bind(this), this.onError.bind(this))
.finally(this.afterResponse.bind(this));
}
private beforeRequest(url: string, body?: string): void {
this._LoaderStore.dispatch({ type: ReducerActions.Loader.Set, payload: true });
}
private afterResponse(): void {
this._LoaderStore.dispatch({ type: ReducerActions.Loader.Set, payload: false });
}
private onCatch(error: any, caught: Observable<Response>): Observable<Response> {
console.log("interceptor catch called");
return Observable.throw(error);
}
private onSuccess(res: Response): void {
let response: ApiResponse<any> = res.json();
if (!response.message) {
return;
}
let toast: ToastModel = {
text: response.message,
duration: 5000,
type: "success"
};
this._ToastStore.dispatch({ type: ReducerActions.Toast.Update, payload: toast });
}
private onError(error: any): void {
let toast: ToastModel = {
text: "Error occurred!",
duration: 5000,
type: "failure"
};
this._ToastStore.dispatch({ type: ReducerActions.Toast.Update, payload: toast });
}
}
I hope this helps :)
Upvotes: 1