如何跟踪Angular HTTP POST调用进度

时间:2018-01-05 12:14:57

标签: angular angular-cli

我试图在我的http调用中放入一个进度条,但有些我怎么能够以异步方式进行同步HTTP调用请求。

以下是进行http呼叫的功能

 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!');
      }
    });

  }

下面是我在我的组件类中用于进行调用的代码,showload是用于显示/隐藏页面预加载器的临时变量。

this.showLoader = false;
      var k = this.myhttpService.authenticationt2c(this.form.get("email").value, this.form.get("password").value);
      this.showLoader = true;

2 个答案:

答案 0 :(得分:1)

我使用以下http服务包装器来访问不同的挂钩,例如handleResponsebeforeRequestafterResponseonCatch& onSuccess

API服务应该使用HttpInterceptor包装器(它在内部触发http调用并允许访问上面提到的钩子)。

注意加载器逻辑是如何在beforeRequest& afterResponse挂钩。

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 });
    }
}

我希望这会有所帮助:)

答案 1 :(得分:1)

正如评论中所提到的,这是异步的,所以当请求需要一些时间来执行时,

this.showLoader = false;
// takes some time to execute
var k = this.myhttpService.authenticationt2c(...);
// executed while waiting for above code to execute
this.showLoader = true;

相反,从您的服务返回一个Observable并在组件订阅中。然后在回调(subscribe)内部切换布尔标志。我猜你要在请求完成后实际将布尔标志showLoader切换到false,所以我在下面切换它们:

this.showLoader = true;
this.myhttpService.authenticationt2c(...)
  .subscribe(() => this.showLoader = false)

并且如上所述,从服务中返回一个Observable,因此请使用map代替subscribe

this.http.request(req).map(event => { ... })

请查看以下链接,了解异步性:How do I return the response from an Observable/http/async call in angular2?How do I return the response from an asynchronous call?