带拦截器的Angular HTTPRequest管道

时间:2019-09-04 04:36:01

标签: angular angular-http-interceptors

我目前正在尝试跟踪角度组件中的上传进度。该组件接受文件并调用服务,该服务会将文件上传到服务器。

我们目前使用拦截器来注入带有auth令牌的标头。

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        if (localStorage.getItem('token') != null) {
            request = request.clone({
                setHeaders: {
                    'X-Auth-Token': localStorage.getItem('token')
                }
            });
        }

        return next.handle(request).pipe(
            map((event: HttpEvent<any>) => {
                return event;
            }),
            catchError((error: any) => {
                if (error.status === 401) {
                    localStorage.removeItem('token');
                    this.router.navigate(['/public/login']);
                    return of(error);
                }
                return throwError(error);
            })
        );

如果在此处的map()后面放置一个tap(),我可以接收到Tap笔记并将其记录到控制台。

我致电服务并尝试使用管道/点击在组件中获取上传进度

 this.assetService.upload(formData).pipe(
      map(data => console.log(data)),
      tap(message => console.log(message))
    ).subscribe(data => { console.log(data); });

这里的pipe()/ map()/ tap()永远不会被命中。

理想情况下,我想使用组件中的tap()来计算上载的百分比,然后使用它来更新进度条。

1 个答案:

答案 0 :(得分:3)

您可以使用此方法或方法使用RxJ的tap/map/pipe

postImportExportFile(fileToUpload: File): Observable<MyObject> {
    this.formData = new FormData();
    this.formData.append('file', fileToUpload, fileToUpload.name);
    const url = 'http://loclahost:4200/myPost/url/to/be/hit';
    return this.http.post(url, this.formData, {
      headers: new HttpHeaders({ 'upload': 'true' }), // I used this for change the interceptors accepts and content-type
      reportProgress: true,
      observe: 'events',
    }).pipe(
      retry(3),
      map((event: HttpEvent<any>) => this.getEventMessage(event, fileToUpload)),
      tap((t: MyObject) => {
        return console.log(`post import export file for );
      }),
      catchError(this.handleError<MyObject>(url))
    );
  }

方法:

getEventMessage(event: HttpEvent<any>, file: File): MyObject{
    const myObject= new MyObject();
    switch (event.type) {
      case HttpEventType.Sent:
        myObject.eventType = UploadEventType.SENT; // This is an enum that help me to add a event type to my object
        myObject.message = `Uploading file "${file.name}" of size ${file.size}.`;
        break;
      case HttpEventType.UploadProgress:
        myObject.eventType = UploadEventType.PROGRESS;
        const percentDone = Math.round(100 * event.loaded / event.total);
        myObject.message = `File "${file.name}" is ${percentDone}% uploaded.`;
        break;
      case HttpEventType.Response:
        console.log(`File "${file.name}" was completely uploaded!`);
        myObject.eventType = UploadEventType.COMPLETED; 
        myObject.message = event;
        break;
      default:
        myObject.eventType = UploadEventType.ERROR;
        myObject.message = `File "${file.name}" surprising upload event: ${event.type}.`;
    }
    return myObject;
  }

收到对象后,您可以检查是否发生了什么情况,并根据需要进行工作。

在第一部分中,我使用了方法postImportExportFile,该方法是后方法调用,并发送一个标头,该标头用于更改拦截器值,如headerSettings['Content-Type'] = 'multipart/form-data';,然后使用观察类型:events

这可以帮助我们获得HttpEvent,然后我们将身边的消息更改为检查和使用。第二种方法可以直接使用,但我将其破坏并用作自己的对象。 希望对您有所帮助。如果您需要进一步澄清代码,请告诉我。