比方说,在我的 Component 中,我有一个Observable
字段,可通过 Service 使用HttpClient
@Component(...)
export class MyComponent {
items$: Observable<readonly Item[]>;
ngOnInit() {
this.items$ = this.findItems();
}
private findItems() {
return this.service
.getItems(...)
.pipe(
// Other code omitted
toArray<Item>()
);
}
}
<app-items [items]="items$ | async"></app-items>
然后,当在MyComponent
内部执行操作时,我需要刷新items$
列表,因此我将 Service
onButtonPressed() {
this.items$ = this.findItems();
}
问题是,Async
管道是否会自动订阅新的Observable
?
考虑到我正在使用detectChanges()
策略,是否需要要求OnPush
?
最重要的是,这是正确的方法吗?
答案 0 :(得分:1)
要回答我自己的问题,是的,如果使用ChangeDetectorRef#detectChanges
变更检测策略,则需要调用OnPush
。
constructor(
...
private readonly changeDetectorRef: ChangeDetectorRef
) {}
onButtonPressed() {
this.items$ = this.findItems();
this.changeDetectorRef.detectChanges();
}
似乎没有一种“更聪明”的方法,即使不使用第二个[Behavior]Subject
。
编辑:我注意到重新分配并调用detectChanges
可能会导致闪烁。
最后,我选择了BehaviorSubject
。
private readonly items = new BehaviorSubject<readonly Item[]>([]);
constructor(...) {
items$ = this.items.asObservable();
}
...
this.findItems().subscribe(items => this.items.next(items));
因此,不再需要重新分配。
答案 1 :(得分:1)
您可能要使用switchMap
管道:
@Component(...)
export class MyComponent {
items$: Observable<readonly Item[]>;
updater$: Subject<void> = new Subject<void>();
ngOnInit() {
this.items$ = this.updater$
.pipe(
switchMap<void, Observable<Items[]>>(() => this.findItems())
)
}
onButtonPressed(){
this.updater$.next();
}
private findItems() {
return this.service
.getItems(...)
.pipe(
// Other code omitted
toArray<Item>()
);
}
}
并仍然使用:
<app-items [items]="items$ | async"></app-items>
switchMap()
允许您有一个“永不重新分配”的可观测值(updater$
),对于此流上的每个发射率,它“切换”该观测值的发射值以发送结果内部函数,应该是可观察的。
在这里,每次调用updater$.next()
时,它都会将发出的void
“切换”到findItems()
方法的结果(即您的项数组)中。
switchMap
和mergeMap
之间的区别在于switchMap
负责完成和关闭先前发出的可观察对象。如果您两次调用updater$.next()
,则第二次调用switchMap
将完成第一次调用findItems()
返回的第一个可观察对象,并将其替换为此方法的新调用。
资料来源:
https://www.learnrxjs.io/operators/transformation/switchmap.html
https://blog.angular-university.io/rxjs-higher-order-mapping/
答案 2 :(得分:0)
异步管道会自动订阅新的Observable吗?
异步管道订阅Observable或Promise并返回其发出的最新值。当组件被销毁时,异步管道将自动退订,以避免潜在的内存泄漏。
考虑到我在OnPush上,我是否需要请求detectChanges() 策略?
您不需要。发出新值时,异步管道会将要检查的组件标记为更改。
这是正确的方法吗? 我看不出有什么害处,因为当组件被销毁时,订阅将自动取消订阅。
答案 3 :(得分:0)
这不是100%肯定的答案,因为它没有记录,但是我们可以从docs中的Promise
管道处理async
中获得一些线索。
greeting: Promise<string>|null = null;
private resolve: Function|null = null;
constructor() {
this.reset();
}
reset() {
this.greeting = new Promise<string>((resolve, reject) => {
this.resolve = resolve;
});
}
在这里我们可以看到重新分配Promise必须触发更改检测,否则代码将无用。