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

标签 javascript angular observable

当尝试通过取消订阅来取消上传时,实际发生的情况是我取消订阅上传进度,但实际上传并未取消并继续上传到服务器。 上传组件.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 => {
     });
  }

   }

上传.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);
    });
   });
  }
 }

如何通过可观察的取消订阅正确取消上传请求 请注意,我已经尝试过 Pipe takeuntil() ,但没有任何改变

最佳答案

您需要做的是从 http 请求返回 observable 上的管道函数返回结果。现在你有多个流,并且组件的取消订阅只是取消订阅包装http请求observable的observable(未连接)。

你会想做这样的事情:

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)执行所需的任何逻辑并反射(reflect)错误等内容并将进度上传到调用服务的组件。在组件方面,您将保留订阅/取消订阅逻辑。

例如,您可以使用switchMap operator转换从 http 请求 observable 返回到组件的内容并指定返回到组件的值,以及 catchError对任何错误做出相应的 react 。

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 函数调用从服务返回到组件并在其中处理订阅中的内容即可。

关于javascript - 取消订阅上传可观察到的 Angular 6停止上传进度但不是实际上传,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54533920/

相关文章:

javascript - 模糊触发时如何限制对字段的验证?

java - 无法在 Angular 6 中将对象发送到 REST API

angular - 如何在运行 ng-build 命令时动态更改 index.html 文件中的内容

javascript - 如果发出相同的可观察值,则取消延迟

angular - 如何使用扫描运算符来计算 void observable 的发射值?

ios - 如何通过 Observable 属性对项目数组进行排序?

javascript - PHP 变量未传输到 fwrite

javascript - 我可以将跨站点 <img/> 标记的数据作为 blob 获取吗?

javascript - 单击后突出显示表行?

javascript - RxJS 5, Angular : How to do a request every x seconds UNTIL a message matches a certain string?