【问题标题】:RxJS Subjects and Angular 2 componentsRxJS 主题和 Angular 2 组件
【发布时间】:2019-04-03 04:49:06
【问题描述】:

我正在接受 Web 开发正在发生变化的事实,我需要掌握 RxJS。我目前正在使用 Angular 2.0.0-beta.15 开发一个网络应用程序。

我在关注最优秀的ng-book 2(允许这种广告吗?哦,好吧)。它广泛而浅薄地涵盖了 RxJS 中的一些重要概念,并提供了进一步阅读的链接。我已经阅读并理解了源代码和随附的解释,但是对于有关 Subjects 的一些细节以及 Angular 2 组件如何使用这些主题流的一些细节,我有些不知所措。

我因此扩充了书中的代码:

export class SubmitResourceComponent {
    private _newResourceTags: Subject<Tag> = new Subject<Tag>();
    private _resourceTags: Observable<Tag[]>;
    private _tagUpdates: Subject<any> = new Subject<any>();
    private _create: Subject<Tag> = new Subject<Tag>();
    private _remove: Subject<Tag> = new Subject<Tag>();

    constructor() {
        this._resourceTags = this._tagUpdates
            .scan((tags: Tag[], operation: ITagsOperation) => operation(tags), initialTags);

        this._create
            .map((tag: Tag): ITagsOperation => (tags: Tag[]) => _.uniq(tags.concat(tag)))
            .subscribe(this._tagUpdates);

        this._remove
            .map((tag: Tag): ITagsOperation => (tags: Tag[]) => _.without(tags, tag))
            .subscribe(this._tagUpdates);

        this._newResourceTags.subscribe(this._create);
    }

    get resourceTags(): Observable<Tag[]> {
        return this._resourceTags;
    } 

    protected addTagToResource(tag: Tag): void {
        this._create.next(tag);
    }

    protected removeTagFromResource(tag: Tag): void {
        this._remove.next(tag);
    }
}

我正在像这样使用_resourceTags

<button class="btn" *ngFor="#tag of resourceTags | async" (click)="removeTagFromResource(tag)">{{ tag.name }}</button>

即使有 gitter 论坛的大力支持,我也无法理解,为什么 UI 会显示所有推入 _resourceTags Subject 的标签。我会想象流就像一根橡皮管:一旦一个元素被推入Subject 并发布到Observer(在这种情况下,是UI 元素),它不会蒸发并消失吗?它是否留在流/管道/Subject 中? UI 元素如何订阅Subject?我是否以错误的方式思考它?我需要彻底的心理重组/移植吗?

这么多问题!

【问题讨论】:

    标签: angular typescript rxjs


    【解决方案1】:

    传递给next 的数据就像一个事件。订阅者获取该值,而由Subject 创建的Observable 不包含对它的任何引用(除非您使用特殊运算符来缓冲或通过其他方式保留发出的值。

    使用| async,Angular 订阅Observable (Subject),当它收到一个值时,它会显示它。

    *ngFor 只渲染数组。如果您想将*ngForSubject 一起使用,则主题需要发出数组 - 每个事件不是单个值,而是一个值数组,这些值由*ngFor 呈现,并在Observable 时替换为其他值发出一个新数组。

    scan operator

    您的代码示例使用scan 运算符,目的是在每次收到*ngFor 要求的新事件时,累积发出的值并转发一个包含迄今为止发出的所有值的数组。

    【讨论】:

    • 因为它使用 RxJS 5,你应该链接到 RxJS 5 文档scan
    • "With | async Angular 订阅了 Observable (Subject),当它接收到一个值时它会显示它。" - 我假设每次通过添加或删除标签来更改“集合”时,所有标签都被推送到 Angular 组件,对吗?它必须这样做,否则您无法删除标签并且此代码正常运行。我想我只需要创建大量日志来准确查看副作用何时发生以及集合在做什么。
    • 不确定“所有标签每次都推送到 Angular 组件”是什么意思。 ...scan() 发出一个新事件,其中包含所有收集到的标签的副本,订阅的*ngFor 根据新接收到的数组重建呈现的元素。
    【解决方案2】:

    我认为 observables 仅在会话被清除之前将变量的值存储在浏览器内存中,就像您如何设置变量以从输入框中获取值并在浏览器上点击刷新时值被清空.在上述场景中,我认为像大多数 SPA 一样,浏览器会被阻止刷新/重新加载的默认行为,并且您会获得某种持久性,因此当您执行类似的操作时

    ...  _.uniq(tags.concat(tag))).subscribe(this._tagUpdates);...
    

    值继续堆积,因为它们被创建事件连接,但在页面上发生手动刷新并清除会话时会消失

    编辑

    也许我的问题错了,但我的意思是: _resourceTags 开始为空,由 create 事件创建一个值,现在 _resourceTags[newValue#1] 角度检测更改并使用 ngFor 重新呈现 _resourceTags,在新的创建事件 _resourceTags 现在是 [newValue#1, newValue#2] 角度重新渲染现在显示两者。如果流没有被持久化到像 firebase 这样的在线数据库或像 websql 这样的离线数据库,这意味着在重新加载浏览器时 _resourceTags 将返回为空

    【讨论】:

    • 不知何故,这个答案似乎与问题无关。
    • 哦,对不起,我以为你想知道这些值怎么可能不会消失
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-15
    • 1970-01-01
    • 1970-01-01
    • 2018-08-14
    相关资源
    最近更新 更多