使用异步管道在Angular模板中解析自定义rxjs主题

时间:2019-08-13 12:56:20

标签: angular rxjs observable behaviorsubject

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

当我接下来调用主题时,我希望模板中的主题能够得到解决。我使用async管道来监听此主题中的异步更改。

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

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

正如您在HelloComponent的模板中看到的那样,我希望观察到的主题customSubject$一旦通过<h1>获得值,就将被呈现为next()

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

如何使用自定义Subject来渲染模板?我需要使用其他管道吗?

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

2 个答案:

答案 0 :(得分:1)

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

enter image description here

这里是各种主题的good resource

答案 1 :(得分:1)

很好的问题。问题在于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);
  }