【问题标题】:Resolve custom rxjs Subject in Angular template using async pipe使用异步管道解决 Angular 模板中的自定义 rxjs 主题
【发布时间】:2019-12-20 00:54:49
【问题描述】:

我的 Angular 应用中有一个自定义的 BehaviourSubject,它在我的模板中用作 Observable。

当我在主题上调用 next 时,我希望模板中的主题得到解决。我使用async 管道来监听这个主题的异步变化。

我在 Stackblitz 中创建了一个示例来显示我遇到的问题:https://stackblitz.com/edit/angular-kmou5e

app.component.ts 中,我创建了一个示例异步方法,它在超时后将值设置为this.data。只要设置了this.datahello.component.ts 就会被初始化并呈现。我在HelloComponent 中收听OnChanges 并在HelloComponent 中的自定义主题上调用next()

正如您在HelloComponent 的模板中看到的,我希望观察到的主题customSubject$ 在通过next() 获得值后立即呈现为<h1>

您可以看到,customSubject$ 的订阅被调用,如日志所示。只有模板不会呈现这个 Observable/Subject。

使用自定义Subject 时如何让模板呈现?我需要使用不同的管道吗?

仅供参考:我还尝试使用 combineLatest 将 Subject 的值分配给新的 Observable,但效果不佳。

【问题讨论】:

标签: angular rxjs observable behaviorsubject


【解决方案1】:

这是一个时间问题。只需将您的主题更改为行为主题(缓存最后发出的值),您的模板就会显示最新发出的值。

这里有一个good resource,关于各种类型的主题。

【讨论】:

  • 将主题更改为 BehaviorSubject 帮助:customSubject$: BehaviorSubject = new BehaviorSubject('initial value');
【解决方案2】:

非常好的问题。问题在于lifecycle hooks 的顺序不保存值,如果运气不好,它只是向订阅者多播。现在生命周期按此顺序运行。构造函数,ngOnChanges,OnNgInit .....然后它加载视图和子组件。因此,为了让您看到这个值,您需要使用 BehaviorSubject 对其进行缓冲。

看看我在说什么

import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
import { combineLatest, Observable, Subject } from 'rxjs';

@Component({
  selector: 'hello',
  template: `<h1>{{ customSubject$ | async }}</h1>
             <h2>{{test}}</h2>
  `
})
export class HelloComponent implements OnChanges  {
  @Input() name: string;
public customSubject$: Subject<string>;

    public test ='Before ngOnChanges run';

  constructor() {
      console.log('constructed');

    this.customSubject$ = new Subject();
    this.customSubject$.subscribe(s => {
      console.log('customSubject$ subscription resolved with ' + s);
    });
  }

  ngOnChanges(changes: SimpleChanges) {
    if (changes.hasOwnProperty('name')) {
      console.log('ngOnChanges is called with ' + this.name);
      this.customSubject$.next(this.name);

    }
          this.test ='After ngOnChanges Ran';
  }
}

你有一个测试变量,它的值在 ngOnChanges 中改变了。您永远不会看到“在 ngOnChanges 运行之前”的值,因为视图尚未初始化。

现在您的*ngIf='data' 让您更加困惑,因为在 ngIf 解析为 true 之前未构造组件

这有助于增加你看到这个的延迟

  ngOnInit() {
    setTimeout(() => {
      this.data = 'some string';
    }, 5000);
  }

【讨论】:

  • 感谢您的非常好的回答,这说明了很多。我在你的例子中看不到你是如何创建 BehaviorSubject 的,很难。
  • 我没有创建它。我只是展示了如何永远不会显示“在 ngOnChanges 运行之前”以及在延迟用完后构造函数将如何执行。只需将主题替换为 BehaviorSubject 即可解决问题,因为它缓冲了最后一个值。如果你推送两个值,在我解释的这种情况下,第一个值将丢失,所以明天我们不会收到与 BehaviorSubject 和 2 条消息相同的问题
猜你喜欢
  • 2020-03-26
  • 2019-07-11
  • 1970-01-01
  • 2020-09-26
  • 2018-07-18
  • 1970-01-01
  • 1970-01-01
  • 2021-12-17
  • 1970-01-01
相关资源
最近更新 更多