使用异步管道解析 Angular 模板中的自定义 rxjs 主题
Resolve custom rxjs Subject in Angular template using async pipe
我的 Angular 应用程序中有一个自定义的 BehaviourSubject,它在我的模板中用作 Observable。
当我在主题上调用 next 时,我希望模板中的主题得到解析。我使用 async
管道来监听此 Subject 中的异步更改。
我在 Stackblitz 中创建了一个示例来说明我遇到的问题:https://stackblitz.com/edit/angular-kmou5e
在 app.component.ts
中,我创建了一个示例异步方法,它在超时后将值设置为 this.data
。一旦设置了 this.data
,hello.component.ts
就会被初始化和渲染。我在 HelloComponent
中收听 OnChanges
并在 HelloComponent
.
中对自定义主题调用 next()
正如您在 HelloComponent
的模板中看到的那样,我希望观察到的主题 customSubject$
在通过 [=18= 获得值后立即呈现为 <h1>
].
您可以看到,调用了 customSubject$
的订阅,如日志中所示。只有模板不呈现此 Observable/Subject.
如何在使用自定义 Subject
时让模板呈现?我需要使用不同的管道吗?
仅供参考:我还尝试使用 combineLatest 将 Subject 的值分配给新的 Observable,但效果不佳。
这是时间问题。只需将您的主题更改为行为主题(缓存最后发出的值),您的模板就会显示最新发出的值。
这里是good resource关于各种主题的。
很好的问题。问题是 lifecycle hooks Subject 的顺序没有值,如果运气不好,它只会向订阅者进行多播。现在生命周期按此顺序运行。构造函数、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 中更改。您永远看不到值 'Before ngOnChanges run',因为视图尚未初始化。
现在您的 *ngIf='data'
让您更加困惑,因为组件不是在 ngIf 解析为 true 之前构造的
它有助于增加你看到这个的延迟
ngOnInit() {
setTimeout(() => {
this.data = 'some string';
}, 5000);
}
我的 Angular 应用程序中有一个自定义的 BehaviourSubject,它在我的模板中用作 Observable。
当我在主题上调用 next 时,我希望模板中的主题得到解析。我使用 async
管道来监听此 Subject 中的异步更改。
我在 Stackblitz 中创建了一个示例来说明我遇到的问题:https://stackblitz.com/edit/angular-kmou5e
在 app.component.ts
中,我创建了一个示例异步方法,它在超时后将值设置为 this.data
。一旦设置了 this.data
,hello.component.ts
就会被初始化和渲染。我在 HelloComponent
中收听 OnChanges
并在 HelloComponent
.
next()
正如您在 HelloComponent
的模板中看到的那样,我希望观察到的主题 customSubject$
在通过 [=18= 获得值后立即呈现为 <h1>
].
您可以看到,调用了 customSubject$
的订阅,如日志中所示。只有模板不呈现此 Observable/Subject.
如何在使用自定义 Subject
时让模板呈现?我需要使用不同的管道吗?
仅供参考:我还尝试使用 combineLatest 将 Subject 的值分配给新的 Observable,但效果不佳。
这是时间问题。只需将您的主题更改为行为主题(缓存最后发出的值),您的模板就会显示最新发出的值。
这里是good resource关于各种主题的。
很好的问题。问题是 lifecycle hooks Subject 的顺序没有值,如果运气不好,它只会向订阅者进行多播。现在生命周期按此顺序运行。构造函数、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 中更改。您永远看不到值 'Before ngOnChanges run',因为视图尚未初始化。
现在您的 *ngIf='data'
让您更加困惑,因为组件不是在 ngIf 解析为 true 之前构造的
它有助于增加你看到这个的延迟
ngOnInit() {
setTimeout(() => {
this.data = 'some string';
}, 5000);
}