当尝试通过取消订阅我取消订阅上传进度的实际情况来取消上传时,但实际的上传未取消并继续上传到服务器。 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(),但未更改
答案 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);
}));
}
}