在不重新运行指定函数的情况下读取可观察变量的值

Reading value of Observable variable without rerunning assigned function

目前我的 angular 组件中有一个功能,每当我想上传文件列表时 运行。

我既要跟踪上传进度然后清空文件列表,又要跟踪上传进度以获得进度条。

我目前的问题是,当我请求 uploadProgress 的值时,它会重新 运行s this.pictureService.upload(this.selectedFiles) 并上传文件两次。

我的函数目前看起来像这样:

uploadImages() {
  // Upload picture and save progress to observable
  const uploadProgress: Observable<HttpEvent<HttpUploadProgressEvent>> = this.pictureService.upload(this.selectedFiles);

  // Create snackbar with observable for progress bar
  this.snackBar.openFromComponent(UploadProgressComponent, {
    data: { uploadProgress },
  });

  // Wait for uploading to be finished and then clear selected files and preview URLs
  uploadProgress.subscribe((event: HttpUploadProgressEvent) => {
    if (event.loaded === event.total && event.loaded !== undefined) {
      this.selectedFiles = null;
      this.previewUrls = [];
    }
  });
}

每次调用 .subscribe 时都会调用可观察对象(参见 here。)

如果您在 openFromComponent 函数中这样做,请考虑不要再次调用 .subscribe,而是像这样:

uploadImages() {
// Upload picture and save progress to observable
const uploadProgress: Observable<HttpEvent<HttpUploadProgressEvent>> = this.pictureService.upload(this.selectedFiles);

// Create snackbar with observable for progress bar
this.snackBar.openFromComponent(UploadProgressComponent, {
  data: {
    uploadProgress.pipe(tap((event: HttpUploadProgressEvent) => {
      if (event.loaded === event.total && event.loaded !== undefined) {
        this.selectedFiles = null;
        this.previewUrls = [];
      }
    }))
  }
})

}

正如 Martin 所建议的,我在常量末尾添加了 .pipe(share()),现在它可以正常工作了。

我的代码现在看起来像这样:

uploadImages() {
  // Upload picture and save progress to observable
  const uploadProgress = this.pictureService.upload(this.selectedFiles).pipe(share());

  // Create snackbar with observable for progress bar
  this.snackBar.openFromComponent(UploadProgressComponent, {
    data: { uploadProgress },
  });

  // Wait for uploading to be finished and then clear selected files and preview URLs
  uploadProgress.subscribe((event: HttpUploadProgressEvent) => {
    if (event.loaded === event.total && event.loaded !== undefined) {
      this.selectedFiles = null;
      this.previewUrls = [];
    }
  });
}