我有一个角分量,它从@Input变量中获取数据,并使用它过滤来自服务的其他数据。(简化)结构如下所示:
<phones-component>
<phone-details>
<..>
<phone-history-component [phoneNumber$]="phoneNumber$"></phone-history-component>
<phone-details>
</phones-component>PhoneDetailsComponent:
changeLogs$: Observable<AuditLog[]>;
constructor(
private auditLogService: AuditLogService, //ngrx-data service
){
ngOnInit(): void {
this.changeLogs$ = combineLatest([this.phoneNumber$, this.auditLogService.entities$])
.pipe(
map(pn => pn[1].filter(logs => logs.pkId === pn[0].id))); //filters the logs to show only log entries from the corresponding phonenumber
}这些路由配置如下:
{
path: 'phones',
component: PhonesComponent,
},
{
path: 'phones/:id',
component: PhoneDetailsComponent,
},只要我从父容器‘输入’PhoneDetailsComponent,一切都能正常工作。当用户手动重新加载PhoneDetails视图时,changeLogs$数组是空的,除非我手动注入一个可观察到的未包装属性,如下所示:
<phone-history-component [phoneNumberId]="(phoneNumber$ | async).id" [phoneNumber$]="phoneNumber$"></phone-history-component>如果我像这样注射电话号码$
[phoneNumber]="(phoneNumber$ | async)"它不起作用。(我在组件中不使用这些额外的输入)
现在我知道还有其他方法来实现这个功能,但是我只想知道为什么代码是这样的呢?
我觉得我对基本的rxjs管道缺乏一些基本的理解。So..what到底在这里发生了什么?
任何帮助都是非常感谢的。
UPDATE BizzyBob是对的。当直接重新加载组件时,当首次执行phoneNumber$函数时,可观察到的filter没有任何值。我用快速检查来修正这个问题:
map(pn => {
return !!pn[0] ? pn[1].filter(logs => logs.pkId === pn[0].id) : null;
}));现在.。这是推荐的方法,还是有更好的方法?
发布于 2020-05-13 13:55:21
要创建正确的rxjs样条,可以使用startWith运算符和switchMap。那么您的代码将如下所示:
ngOnInit(): void {
this.changeLogs$ = this.phoneNumber$
.pipe(
startWith({}),
switchMap(item => this.filterData(item))
);
}
filterData(value = {}): Observable<any>{
return this.auditLogService.entities$
.pipe(
map(data => data.filter(logs => logs.pkId === value.id))
);
}发布于 2020-05-13 12:44:17
phoneNumber$是如何定义的?这可能是formControl.valueChanges可以观察到的吗?这不会调用初始值,因此可以使用rxjs startWith()操作符。如果你不能使用它(因为一些奇怪的原因),那么BehaviorSubject是下一个选择。
我用代码片段复制了您的问题,并提供了2种推荐的解决方案。瞧一瞧!
let changeLogs$ = null;
let phoneNumber$ = null;
let auditLogService = {
entities$: rxjs.of([{pkId: 1}])
}
function ngOnInit() {
changeLogs$ = rxjs.combineLatest([phoneNumber$, auditLogService.entities$])
.pipe(
rxjs.operators.map(pn => pn[1].filter(logs => logs.pkId === pn[0].id)))
}
console.log('empty observable');
phoneNumber$ = rxjs.of();
ngOnInit();
let subscribtion = changeLogs$.subscribe(data => console.log(data));
subscribtion.unsubscribe();
console.log('observable with data');
phoneNumber$ = rxjs.of({id: 1})
ngOnInit();
subscribtion = changeLogs$.subscribe(data => console.log(data));
subscribtion.unsubscribe();
console.log('empty observable with startWith');
phoneNumber$ = rxjs.of().pipe(rxjs.operators.startWith({id: 1}));
ngOnInit();
subscribtion = changeLogs$.subscribe(data => console.log(data));
subscribtion.unsubscribe();
console.log('behaviorsubject with data');
phoneNumber$ = new rxjs.BehaviorSubject({id: 1})
ngOnInit();
subscribtion = changeLogs$.subscribe(data => console.log(data));<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.5/rxjs.umd.js"></script>
https://stackoverflow.com/questions/61732780
复制相似问题