【问题标题】:Why is not Subject.next () emission detected in Angular template with async pipe?为什么在带有异步管道的 Angular 模板中未检测到 Subject.next () 发射?
【发布时间】:2021-02-09 16:58:48
【问题描述】:

有以下代码,我想知道 为什么 Subject.next(1) 发射在模板中不可见,而 BehaviorSubject.next() 发射是可见的。

我知道将它包装在 setTimeout() 中可以解决问题,但我想了解它。

我好像Subject.next()同步 并且async 管道没有接收/标记检查。

@Component({
  selector: 'my-app',
  template: `
    <div>Subj: {{ subj$ | async }}</div>
    <div>BehavSubj: {{ behavSubj$ | async }} </div>
    <div>Interval: {{ interval$ | async }} </div>
  `,
  styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
  subj$ = new Subject<number>();
  behavSubj$ = new BehaviorSubject<number>(1);
  interval$ = interval(1000).pipe(take(100));

  ngOnInit(): void {
    this.subj$.next(1);
    this.behavSubj$.next(2);
  }
}

https://stackblitz.com/edit/angular-ivy-crnfgc?file=src/app/app.component.ts

【问题讨论】:

  • 阅读主题。他们不会向迟到的订阅者发出最后发出的值。您的异步管道订阅是在下次通话后进行的
  • 未检测到,因为时间太早了。将所有出现的OnInit 替换为AfterViewInit 即可。
  • 一个 BehaviorSubject 有 replay 行为,而普通的 Subject 没有。
  • 我还没有意识到,这是时间问题????‍♂️,谢谢您的解释。

标签: angular async-pipe


【解决方案1】:

未检测到,因为它太早了。将所有出现的OnInit 替换为AfterViewInit 即可。

import { Component, AfterViewInit, OnInit, VERSION } from "@angular/core";
import { BehaviorSubject, interval, Subject } from "rxjs";
import { take } from "rxjs/operators";

@Component({
  selector: "my-app",
  template: `
    <div>Subj: {{ subj$ | async }}</div>
    <div>BehavSubj: {{ behavSubj$ | async }}</div>
    <div>Subj: {{ subj2$ | async }}</div>
    <div>BehavSubj: {{ behavSubj2$ | async }}</div>
    <div>Interval: {{ interval$ | async }}</div>
  `,
  styleUrls: ["./app.component.css"]
})
export class AppComponent implements OnInit, AfterViewInit {
  subj$ = new Subject<number>();
  behavSubj$ = new BehaviorSubject<number>(1);
  subj2$ = new Subject<number>();
  behavSubj2$ = new BehaviorSubject<number>(1);
  interval$ = interval(1000).pipe(take(100));

  ngOnInit(): void {
    this.subj$.next(1);
    this.behavSubj$.next(2);
  }

  ngAfterViewInit(): void {
    this.subj2$.next(1);
    this.behavSubj2$.next(2);
  }
}

首先,您必须初始化视图,以便异步管道已被订阅。然后你可以向一个简单的主题发送一个值。行为主体不同。它存储它的最后一个值。您可以先更新一个行为主题,然后再订阅。这也是为什么你必须初始化一个行为主体但初始化一个基本主体没有意义的原因。

Here 就是一个例子。

【讨论】:

  • 非常感谢!我花了两天时间了解我的类似案例
猜你喜欢
  • 1970-01-01
  • 2019-07-17
  • 2019-07-11
  • 2018-05-30
  • 1970-01-01
  • 2021-10-18
  • 2018-02-20
  • 2020-04-18
  • 1970-01-01
相关资源
最近更新 更多