Angular-Observables合并结果多次调用

时间:2018-07-29 21:57:11

标签: angular typescript rxjs observable combinelatest

编辑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)))
}

该代码基本上是做什么的:它将两个可观察对象的结果组合在一起,然后检查每个对象是否返回了任何值。如果两个可观察值都具有值,则返回 true ,否则返回 false

到目前为止,一切正常。然后,我从View中调用该方法,为可观察对象提供动态节点引用,并使用布尔值添加条件元素:

<div *ngIf="getBoolean('dataN', 'dataK') | async"> My lovely div content goes here</div>

但是,我的div根本不显示在视图上。

有人可以告诉我我做错了什么,可以帮助我达到预期的结果吗?

3 个答案:

答案 0 :(得分:1)

getBoolean()未返回任何内容。订阅回调内部的返回将返回订阅。一种实现此逻辑的方法。

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>

答案 1 :(得分:0)

首先,您的应用程序陷入了无限循环,因为您将视图与返回的函数绑定在一起,该函数不会返回任何内容。此外,我不建议从视图中绑定函数,而是将其绑定到变量。
您可能尝试添加一个BehaviorSubject,它将视图和逻辑绑定到正确的值。
我已经做了一个沙箱,只是检查它是否有效,而且确实可以。

  

TL; DR-我只构造了两个BehaviorSubject来操纵   第三个,在您的情况下是所需的布尔值。我绑定   通过CombineLatest将div分配给第三个BSubject,它可以正常工作。关键是要始终绑定一个有效的变量,该变量通过combinateLatest的订阅进行更新,而我通过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


祝你好运!

答案 2 :(得分:0)

最有可能的问题是,您正在模板中调用getBoolean('dataN', 'dataK')方法。每次更改检测时,Angular都会调用getBoolean方法,该方法返回一个新的Observable。旧版本已取消订阅async,只有新版本处于活动状态。

同时combineLatest运算符要求所有源Observable至少发射一次,这不太可能发生,因为async在不断变化的检测周期中进行订阅/取消订阅,该周期可能多次发生。第二。

所以我建议您将Observable存储在一个属性中:

public obs$ = combineLatest(myFirstObservable, mySecondObservable, (data1, data2) => data1 && data2);

然后仅在模板中使用obs$ | async

最终,您可以在getBoolean内添加一些逻辑,以检查obs$是否存在,如果存在则直接将其返回。