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



我在组件中有以下属性:

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 observable是更好的方法吗?或者在angular中这样做的常见习惯用法是什么?

我将尝试解释现在发生了什么,为什么不建议使用它,以及一种替代方法。

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

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

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

您的示例很有效,因为您在Angular区域内创建了promise。当您在一个区域内并创建了一个异步侦听器时,Angular将模拟修补该操作,以便在异步操作完成时进行Angular更改检测。

await this.blobStorageService.upload(...)

因此,上面的代码行是在一个区域内执行的,当async完成时,Angular将遍历所有组件视图,看看是否有任何更改。然后,它将渲染任何脏的组件。

我来自react世界,正在观察类似这样的属性变化。

你肯定不会在React中这样做,我不能诚实地说我喜欢Angular的这一方面。

开箱即用的Angular不太需要了解视图、分区和更改检测的工作原理。您可以执行这样的操作并快速创建一个可工作的应用程序,但它不能扩展到更大的应用程序。随着从组件添加越来越多的视图,更改检测速度会减慢并开始滞后。

我们称之为技术债务,因为如果您的应用程序的大小增加,那么您将不得不回去重构,以使用OnPush更改检测。Angular中的此功能使您烧伤之后,您将始终使用OnPush

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

作为React开发人员。你很早就发现了这一点,只是觉得错了,但你不明白为什么,我认为这确实证明了React为什么如此受欢迎。它解决了Angular中的一个重要问题,从一开始就不允许这个问题存在。

我只想知道angular devs是这样做的,还是他们使用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()函数以发出值,但我不想尝试为您重写它。我认为这不是真正的问题所在。

最新更新