使用rxjs观察角度为4的数组中的变化

时间:2019-02-07 14:29:59

标签: angular

我在组件中具有以下属性:

  get isUploading() {
    return this.files.length > 0 && this.files.some((f) => f.state === FileUpLoadState.uploading);
  }

然后我有一个绑定到该属性的进度组件:

<md-progress-bar *ngIf="this.isUploading" mode="indeterminate">loading...
</md-progress-bar>

我有一个上传功能,该功能可以遍历文件对象数组并直接更改对象数组:

 upload(){
    this.files.forEach(async (uploadedFile) => {
      uploadedFile.state = FileUpLoadState.uploading;

      try {
        uploadResponse = await this.blobStorageService.upload(uploadedFile.file, {
          maxSingleShotSize,
          progress: (progress) => file.progress = progress.
        });

        uploadedFile.state = FileUpLoadState.success;

        this.uploadActions.persistUpload({ ...uploadedFile, ...uploadResponse });
      } catch (err) {
        uploadedFile.error = err.message;
        uploadedFile.state = FileUpLoadState.error;
      }
    });
  }

我来自反应世界,正在观察属性变化,这不是您要做的。

使用可观察的rxjs会是更好的方法,还是用角度的通用用法?

1 个答案:

答案 0 :(得分:2)

我将尝试解释现在正在发生的事情以及为什么不建议这样做以及替代方法。

get isUploading() {
   return this.files.length > 0 && this.files.some((f) => f.state === FileUpLoadState.uploading);
}

上面是一个 state 属性,其中该值由upload()异步 进行了突变。 Angular将需要呈现组件的视图以反映HTML中的任何更改。这些都是通过更改检测自动完成的,您看到这些更改的原因是因为Angular使用区域来检测触发更改检测的异步操作。

https://www.joshmorony.com/understanding-zones-and-change-detection-in-ionic-2-angular-2/

您的示例可行,因为您正在Angular区域内创建诺言。当您位于区域中并创建异步侦听器时,Angular将嘲笑该操作,以便在异步操作完成时进行Angular更改检测。

await this.blobStorageService.upload(...)

因此,上面的代码行是在区域内执行的,异步完成后,Angular会浏览所有组件视图以查看是否已更改。然后它将渲染所有脏的组件。

  

我来自反应世界,正在观察像这样的财产变化。

您肯定不会在React中做到这一点,并且我不能坦白地说我喜欢Angular的这一方面。

开箱即用,Angular对视图,区域和变更检测的工作原理了解较少。您可以执行以下操作并快速创建一个可以运行的应用程序,但是它不能扩展到更大的应用程序。当您从组件中添加越来越多的视图时,更改检测会变慢并开始滞后。

我们之所以将此称为“技术债务”,是因为如果您的应用程序规模不断扩大,那么您将不得不返回并重构事物以使用OnPush变更检测。在Angular中将此功能烧掉后,之后您将始终从那里使用OnPush

https://netbasal.com/a-comprehensive-guide-to-angular-onpush-change-detection-strategy-5bac493074a4

作为React开发人员。您很早就发现了 ,只是感觉错误,但是您不明白为什么,我认为这确实说明了React如此受欢迎的原因。通过从不让问题首先出现,它解决了Angular中的一个重要问题。

  

我只想知道这是Angular开发人员是如何做这种事情的,还是他们使用rxjs

因此,推荐的方法是使用OnPush更改通知。将组件配置为使用OnPush后,异步操作完成后,将不会更新其视图。 Angular将不会检测到更改,因为所有输入绑定都没有更改。

现在,我们实际上可以更好地回答您的问题。异步操作更改后,如何更新视图?

将视图标记为肮脏

您可以将ChangeDetectRef类注入组件,然后将视图标记为肮脏。

https://angular.io/api/core/ChangeDetectorRef#markforcheck

当响应式编程要求您重构源代码,或者根本无法使用响应式编程时,这是迄今为止最简单的解决方案。

    this.uploadActions.persistUpload({ ...uploadedFile, ...uploadResponse });
    this.changeDetectorRef.markforcheck();

您只需在代码中添加一行,这将告诉Angular该组件很脏。

我不会说这是一种最佳实践,但这是您如何使其与OnPush一起使用的方法,这才是重要的。现在,仅在实际更改时才需要更新该组件,并且Angular不必一直检测到更改。

使用异步进行反应式编程

反应式编程允许您使用async管道更新视图。

https://angular.io/api/common/AsyncPipe

优点是管道可以将视图标记为肮脏。因此,您可以创建一个使用OnPush并响应异步操作的组件,而不必一直手动调用markforcheck()

您的模板将变为:

<md-progress-bar *ngIf="isUploading | async" mode="indeterminate">loading...

该属性将是可观察的,发出真/假值。有很多方法可以转换您的upload()函数以发出值,但是我不想尝试为您重写它。我认为这并不是问题所在。