Angular - Observables 组合结果多次调用
Angular - Observables combined result multiple calls
编辑 30-07-2018 01:57 CET: 仍在寻找以下问题的解决方案:
我有以下代码:
getBoolean(dataRef1, dataRef2) {
const myFirstObservable = this.af.object(dataRef1).valueChanges();
const mySecondObservable = this.af.object(dataRef2).valueChanges();
return combineLatest(myFirstObservable, mySecondObservable).pipe(map(([data1, data2]) => data1 && data2)))
}
基本上代码所做的是:它结合了两个可观察对象的结果,然后检查每个对象是否具有 returned 任何值。如果两个 observables 都有一个值,return true else return false.
到目前为止一切顺利,一切都按预期进行。然后我从我的视图中调用该方法,为可观察对象提供动态节点引用,并使用布尔值添加条件元素:
<div *ngIf="getBoolean('dataN', 'dataK') | async"> My lovely div content goes here</div>
但是,我的 div 根本没有显示在我的视图中。
谁能告诉我我哪里错了并帮助我达到我想要的结果?
getBoolean()
return什么都没有。订阅回调中的 return 是订阅的 returning。一种实现此逻辑的方法。
getBoolean(dataRef1, dataRef2): Observable<boolean> {
const myFirstObservable = this.af.object(dataRef1).valueChanges();
const mySecondObservable = this.af.object(dataRef2).valueChanges();
return combineLatest(myFirstObservable, mySecondObservable, (data1, data2) => data1 && data2)
}
魔术:您使用 async
管道 link 在 HTML 中订阅,它将为您订阅:
<div *ngIf="getBoolean('dataN', 'dataK') | async"> My lovely div content goes here</div>
首先,您的应用程序陷入了无限循环,因为您使用 returned 函数绑定了您的视图,而该函数并没有 return 任何内容。此外,我不建议从视图绑定函数,而是绑定到变量。
您可能会尝试添加一个将视图和逻辑绑定到正确值的 BehaviorSubject。
我制作了一个沙箱来检查它是否有效,它确实有效。
TL;DR - I just construct two BehaviorSubject to manipulate the value of
the third one, which in your case is the desired boolean value. I bind
the div to the third BSubject through combineLatest and it works. The point is to keep always a valid variable to bind, which get updated via the subscription of the combineLatest, and I update its value through the BehaviorSubject
k1 = new BehaviorSubject<boolean>(false);
k2 = new BehaviorSubject<boolean>(false);
k3 = new BehaviorSubject<boolean>(false);
k3$: Observable<boolean>;
constructor() {
this.k3$ = this.k3.asObservable();
}
ngOnInit() {
combineLatest(this.k1.asObservable(), this.k2.asObservable(), (d1, d2) => {
return d1 && d2;
}).subscribe(b => {
console.log(b);
this.k3.next(b);
});
}
toggle1 = () => {
this.k1.next(true);
};
toggle2 = () => {
this.k2.next(true);
};
并在 HTML 中:
<div *ngIf='k3$ | async'>
Example
</div>
有效,请尝试查看示例并将其投射到您的代码中。
Check the CodeSandbox Example
祝你好运!
问题很可能是您在模板中调用了 getBoolean('dataN', 'dataK')
方法。在每个变化检测中,Angular 调用 getBoolean
方法,return 是一个新的 Observable。旧的被async
取消订阅,只有新的活跃。
同时 combineLatest
运算符要求所有源 Observable 至少发出一次,这不太可能发生,因为 async
subscribes/unsubscribes 在可能发生的任何变化检测周期中一秒钟多次。
所以我建议您将 Observable 存储在 属性:
public obs$ = combineLatest(myFirstObservable, mySecondObservable, (data1, data2) => data1 && data2);
然后仅在模板中使用 obs$ | async
。
最后,您可以在 getBoolean
中添加一些逻辑来检查 obs$
是否存在,如果存在,您将按原样 return 它。
编辑 30-07-2018 01:57 CET: 仍在寻找以下问题的解决方案:
我有以下代码:
getBoolean(dataRef1, dataRef2) {
const myFirstObservable = this.af.object(dataRef1).valueChanges();
const mySecondObservable = this.af.object(dataRef2).valueChanges();
return combineLatest(myFirstObservable, mySecondObservable).pipe(map(([data1, data2]) => data1 && data2)))
}
基本上代码所做的是:它结合了两个可观察对象的结果,然后检查每个对象是否具有 returned 任何值。如果两个 observables 都有一个值,return true else return false.
到目前为止一切顺利,一切都按预期进行。然后我从我的视图中调用该方法,为可观察对象提供动态节点引用,并使用布尔值添加条件元素:
<div *ngIf="getBoolean('dataN', 'dataK') | async"> My lovely div content goes here</div>
但是,我的 div 根本没有显示在我的视图中。
谁能告诉我我哪里错了并帮助我达到我想要的结果?
getBoolean()
return什么都没有。订阅回调中的 return 是订阅的 returning。一种实现此逻辑的方法。
getBoolean(dataRef1, dataRef2): Observable<boolean> {
const myFirstObservable = this.af.object(dataRef1).valueChanges();
const mySecondObservable = this.af.object(dataRef2).valueChanges();
return combineLatest(myFirstObservable, mySecondObservable, (data1, data2) => data1 && data2)
}
魔术:您使用 async
管道 link 在 HTML 中订阅,它将为您订阅:
<div *ngIf="getBoolean('dataN', 'dataK') | async"> My lovely div content goes here</div>
首先,您的应用程序陷入了无限循环,因为您使用 returned 函数绑定了您的视图,而该函数并没有 return 任何内容。此外,我不建议从视图绑定函数,而是绑定到变量。
您可能会尝试添加一个将视图和逻辑绑定到正确值的 BehaviorSubject。
我制作了一个沙箱来检查它是否有效,它确实有效。
TL;DR - I just construct two BehaviorSubject to manipulate the value of the third one, which in your case is the desired boolean value. I bind the div to the third BSubject through combineLatest and it works. The point is to keep always a valid variable to bind, which get updated via the subscription of the combineLatest, and I update its value through the BehaviorSubject
k1 = new BehaviorSubject<boolean>(false);
k2 = new BehaviorSubject<boolean>(false);
k3 = new BehaviorSubject<boolean>(false);
k3$: Observable<boolean>;
constructor() {
this.k3$ = this.k3.asObservable();
}
ngOnInit() {
combineLatest(this.k1.asObservable(), this.k2.asObservable(), (d1, d2) => {
return d1 && d2;
}).subscribe(b => {
console.log(b);
this.k3.next(b);
});
}
toggle1 = () => {
this.k1.next(true);
};
toggle2 = () => {
this.k2.next(true);
};
并在 HTML 中:
<div *ngIf='k3$ | async'>
Example
</div>
有效,请尝试查看示例并将其投射到您的代码中。 Check the CodeSandbox Example
祝你好运!
问题很可能是您在模板中调用了 getBoolean('dataN', 'dataK')
方法。在每个变化检测中,Angular 调用 getBoolean
方法,return 是一个新的 Observable。旧的被async
取消订阅,只有新的活跃。
同时 combineLatest
运算符要求所有源 Observable 至少发出一次,这不太可能发生,因为 async
subscribes/unsubscribes 在可能发生的任何变化检测周期中一秒钟多次。
所以我建议您将 Observable 存储在 属性:
public obs$ = combineLatest(myFirstObservable, mySecondObservable, (data1, data2) => data1 && data2);
然后仅在模板中使用 obs$ | async
。
最后,您可以在 getBoolean
中添加一些逻辑来检查 obs$
是否存在,如果存在,您将按原样 return 它。