Angular 带拦截器的 HTTPRequest 管道

Angular HTTPRequest pipe w/ interceptor

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

我们目前使用拦截器注入 header 和 auth-token。

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(),我可以接收点击注释并将它们记录到控制台。

我调用该服务并尝试使用 pipe/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() 来计算上传的百分比,然后用它来更新进度条。

您可以使用此方法或方式使用 RxJs 的 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;
  }

收到 object 后,您可以使用 if else case 检查事件是什么,然后根据需要进行工作。

在第一部分中,我使用了方法 postImportExportFile,它是 post 方法调用并发送一个 header 用于更改拦截器值,例如 headerSettings['Content-Type'] = 'multipart/form-data';,然后使用 observe输入:如 events

这有助于我们获取 HttpEvents,然后我们更改消息在我们这边进行检查和使用。第二种方法你可以直接使用,但我打破了它们并用作我自己的 object。 希望对您有所帮助,如果您需要进一步说明代码,请告诉我。