【发布时间】:2021-06-15 04:14:04
【问题描述】:
我正在开发一个 Angular 应用程序和其他功能,现在我正在开发一个图片库(轮播)。
当用户打开图片库时,他还可以上传新照片。
因为我需要了解全局的上传过程,所以我正在尝试为此实现一个服务,如下所示:
在 ts 组件中我有以下功能:
onUploadFile(files: File[]) {
if (!files?.length) {
return;
}
const uploading = this.attachmentsService
.uploadMultiple(files)
.map((x) => ({ attachment: x }));
uploading.forEach((file) => {
this.filesStateService
.getProgress(file.attachment.url)
.pipe(untilDestroyed(this))
.subscribe({
complete: () => {
this.referenceAttachments = [...this.referenceAttachments];
},
error: () => {
this.deleteAttachment(file);
},
});
});
this.referenceAttachments = [...uploading, ...this.referenceAttachments];
}
attachments.service.ts:
uploadMultiple(files: File[]) {
if (!files?.length) {
return [];
}
return files.map((x) => this.upload(x));
}
upload(file: File) {
const fileUpload = this.filesService.upload(file);
this.filesStateService.addProgress(fileUpload.url, fileUpload.progress$);
const attachment: Attachment = {
url: fileUpload.url,
size: file.size,
type: file.type,
};
return attachment;
}
files.service.ts:
upload(file: File) {
...
return {
url: fileUrl,
progress$: new Observable<number>((observer) => {
blockBlobClient
.uploadData(file, {
onProgress: this.onProgress(observer),
})
.then(
this.onUploadComplete(observer, file, fileUrl),
this.onUploadError(observer, fileUrl)
);
}).pipe(distinctUntilChanged(), startWith(0), shareReplay()),
};
}
private onUploadError(observer: Subscriber<number>, fileUrl: string) {
return (error: any) => {
observer.error(error);
this.filesStateService.removeProgress(fileUrl);
};
}
private onUploadComplete(
observer: Subscriber<number>,
file: File,
fileUrl: string
) {
return () => {
observer.next(file.size);
this.filesStateService.removeProgress(fileUrl);
observer.complete();
};
}
private onProgress(observer: Subscriber<number>) {
return (progress: TransferProgressEvent) =>
observer.next(progress.loadedBytes);
}
在视图中,进度渲染如下:
<app-file-upload-progress
*ngIf="file.attachment.url | fileProgress | async as progress"
[progress]="progress"
[size]="file.attachment?.size"
></app-file-upload-progress>
file-progress.pipe 只是从列表中返回进度:
@Pipe({
name: 'fileProgress',
})
export class FileProgressPipe implements PipeTransform {
constructor(private filesStateService: FilesStateService) {}
transform(value: string): Observable<number> {
if (!value) {
return null;
}
return this.filesStateService.getProgress(value);
}
}
以及存储文件进度的files-state.service:
@Injectable()
export class FilesStateService {
filesProgress: Map<string, Observable<number>> = new Map();
addProgress(url: string, progress$: Observable<number>): void {
this.filesProgress.set(url, progress$);
}
removeProgress(url: string): void {
this.filesProgress.delete(url);
}
getProgress(url: string): Observable<number> {
return this.filesProgress.get(url);
}
}
不明白为什么,文件上传成功后,进度从filesProgress列表中删除后,app-file-upload-progress并没有从界面中删除。
我还尝试在 file-progress.pipe 中使用pure: false,这样,上传完成后,如果我单击另一个元素,则会反映更改并从中删除进度UI(但据我所知,使用pure: false 会导致性能不佳。
【问题讨论】:
标签: angular typescript rxjs-observables