取消订阅上传可观察到的角度6停止上传进度,但不是实际上传

时间:2019-02-05 11:58:01

标签: javascript angular observable

当尝试通过取消订阅我取消订阅上传进度的实际情况来取消上传时,但实际的上传未取消并继续上传到服务器。 upload.components.ts

import { Component, OnInit, Input, Output, EventEmitter, OnDestroy } from '@angular/core';
import { Subject, Subscription, Observable } from 'rxjs';
import { HttpEventType } from '@angular/common/http';
import { UploadService } from '../../../services';
import { takeUntil } from 'rxjs/operators';

 @Component({
 selector: 'app-image-upload-item',
  templateUrl: './image-upload-item.component.html',
  styleUrls: ['./image-upload-item.component.scss']
  })
 export class ImageUploadItemComponent implements OnInit, OnDestroy {
  @Input() index: any;
  @Output() uploadSuccess: EventEmitter<any>;
  @Output() uploadCanceled: EventEmitter<any>;
  public localimageURL: string;
  public uploadProgress: number;
  public isUploadCompleted: boolean;
  public uploadImageObservable: Subscription;
  public isReadyForUpload: boolean;
   public isUploading: boolean;
   public progressMode: string;
  public readonly unique: string = Math.floor((Math.random() * 
   100)).toString();
   public readonly imagePreviewID = 'imagePreview' + this.unique;


      _file: any;
     @Input() public set file(value: any) {
     const reader = new FileReader();
     reader.onload = (e: any) => {
      this.localimageURL = e.target.result;
    };
     this._file = value;
    reader.readAsDataURL(this._file);
    console.log(this._file);


     }
    constructor(private uploadService: UploadService) {
     this.uploadProgress = 0;
     this.isUploading = false;
     this.localimageURL = '';
      this.isUploadCompleted = false;
      this.uploadSuccess = new EventEmitter<any>();
      this.uploadCanceled = new EventEmitter<any>();
      this.progressMode = 'indeterminate';
       }

     ngOnInit() {
       this.uploadImageToServer(this._file);

      // setTimeout(() => {
      //   console.log('im in set time out unsubscripting', 
        this.uploadImageObservable);
      //    this.uploadImageObservable.forEach(subscription => {
     //     subscription.unsubscribe();
      //   });
   // }, 100);
   }

  ngOnDestroy() {
    console.log('component destroyed');
    this.uploadImageObservable.unsubscribe();
    }
    public clearUploadButtonClicked() {
    // if (this.uploadImageObservable !== undefined) {
   //   console.log('image observable is defined');
   //   this.uploadImageObservable.unsubscribe();
   //   console.log(this.uploadImageObservable.closed);
  // }
    // this.uploadImageObservable.unsubscribe();
   this._file = '';
    this.uploadCanceled.emit({ index: this.index, uploaded: false });
  }

   public get showUploadProgress(): boolean {
    return this.uploadProgress !== 0;
   }


   public uploadImageToServer(file) {
     this.isUploading = true;
    const progress = new Subject<number>();
     progress.subscribe(value => {
       this.uploadProgress = value;
     });

   this.uploadImageObservable = this.uploadService.uploadImage(file)
    .subscribe(result => {
      const type = result.type;
      const data = result.data;
      console.log(result);

       if (type === HttpEventType.UploadProgress) {
        const percentDone = Math.round(100 * data.loaded / data.total);
        progress.next(percentDone);
        if (percentDone === 100) {
          this.progressMode = 'indeterminate';
         }
        } else if (type === HttpEventType.Response) {
          if (data) {
            progress.complete();
           this.progressMode = 'determinate';
           this.isReadyForUpload = false;
           this.isUploadCompleted = true;
           this.isUploading = false;
            this.uploadSuccess.emit({ index: this.index, mediaItem: data });
          }

       }
     }, errorEvent => {
     });
  }

   }

upload.service.ts

  public uploadImage(imageFile: File): Observable<any> {
    const formData: FormData = new FormData();
     if (imageFile !== undefined) {
       formData.append('image', imageFile, imageFile.name);

      const req = new HttpRequest('POST', environment.uploadImageEndPoint, 
      formData, {
      reportProgress: true,
    });

   return new Observable<any>(observer => {
     this.httpClient.request<any>(req).subscribe(event => {
    if (event.type === HttpEventType.Response) {
      const responseBody = event.body;
      if (responseBody) {
        this.alertService.success(responseBody.message);
        observer.next({ type: event.type, data: new 
      MediaItem(responseBody.mediaItem) });
      }
    } else if (event.type === HttpEventType.UploadProgress) {
      observer.next({ type: event.type, data: { loaded: event.loaded, total: 
   event.total } });

    } else {
      observer.next(event);
    }
  }, errorEvent => {
    if (errorEvent.status === 400) {
      this.alertService.error(errorEvent.error['image']);
    } else {
      this.alertService.error('Server Error, Please try again later!');
    }
    observer.next(null);
    });
   });
  }
 }

如何观察到取消订阅,才能正确取消上传请求 注意,我已经尝试过管道takeuntil(),但未更改

2 个答案:

答案 0 :(得分:0)

您要做的是从可观察的http请求返回的管道函数返回结果。现在,您有多个流,并且组件的取消订阅仅取消订阅可观察的包装,而可包装的HTTP请求是可观察的(未连接)。

您需要执行以下操作:

return this.httpClient.request<any>(req).pipe(
    // use rxjs operators here
);

然后,您将使用rxjs operators (I've been doing this for a while, but I still highly reference this site)执行所需的任何逻辑,并反映诸如错误之类的内容,并将进度上传到调用该服务的组件。在组件方面,您将保留您的订阅/取消订阅逻辑。

例如,您可以使用switchMap operator来转换可从http请求中观察到的返回给组件的内容,并指定要返回给组件的值,并使用catchError对任何错误做出相应的反应

return this.httpClient.request<any>(req).pipe(
    switchMap(event => {
        if (event.type === HttpEventType.Response) {
            const responseBody = event.body;
            if (responseBody) {
                this.alertService.success(responseBody.message);
                return { type: event.type, data: new MediaItem(responseBody.mediaItem) };
            }
        } else if (event.type === HttpEventType.UploadProgress) {
            return { type: event.type, data: { loaded: event.loaded, total: event.total } };
        }
        return event;
    }),
    catchError(errorEvent => {
        if (errorEvent.status === 400) {
            this.alertService.error(errorEvent.error['image']);
        } else {
            this.alertService.error('Server Error, Please try again later!');
        }
        return of(<falsy or error value>);
    }),
);

或者,您可以在this example之后对其建模,只需将http函数调用从服务返回到组件并在其中处理预订中的事情。

答案 1 :(得分:0)

实际上我找到了一种方法

public uploadImage(imageFile: File): Observable<any> {
const formData: FormData = new FormData();
if (imageFile !== undefined) {
  formData.append('image', imageFile, imageFile.name);

  const req = new HttpRequest('POST', environment.uploadImageEndPoint, formData, {
    reportProgress: true,
  });

  return this.httpClient.request<any>(req).pipe(
    map((res: any) => {
      return res;
    }),
    catchError(errorEvent => {
      if (errorEvent.status === 400) {
        this.alertService.error(errorEvent.error['image']);
      } else {
        this.alertService.error('Server Error, Please try again later!');
        return Observable.throw(errorEvent);
      }
      return Observable.throw(errorEvent);
    }));
}

}