Angular2合并可观察量

时间:2016-07-14 13:54:48

标签: typescript angular rxjs

我遇到一些可观察的东西时遇到了麻烦。我似乎无法得到两个 可观察到放在一起很好。他们自己工作得很好,但我 需要两个值。

db.glass.subscribe( ( glass: GlassData[] ): void => {
  console.log( glass ); // This prints
});

db.cassette_designs.subscribe( ( cassettes: CassetteData[] ): void => {
  console.log( cassettes ): // This prints
});

对于可观察者并不熟悉,我尝试的第一件事就是 将一个嵌套在另一个内部,但内部似乎没有做任何事情。

db.glass.subscribe( ( glass: GlassData[] ): void => {
  console.log( glass ); // This prints

  db.cassette_designs.subscribe( ( cassettes: CassetteData[] ): void => {
    console.log( cassettes ): // This doesn't
  });
});

这似乎有点傻,所以我在Google上搜索是否有 更好的方法来结合可观察量,事实证明有一些。我试过了 zipforkJoin,因为它们看起来最像我想做的事,但是 也没有什么能与他们合作。

Observable.zip( db.cassette_designs, db.glass, ( cassettes: CassetteData[], glass: GlassData[] ): void => {
  console.log( cassettes ); // doesn't print
  console.log( glass     ); // doesn't print
});

Observable.forkJoin( [ db.cassette_designs, db.glass ] ).subscribe( ( data: any ): void => {
  console.log( data ); // doesn't print
});

这可能是一件简单的事情,因为我没有正确地调用函数,但是 我原本以为我会在某些时候得到某种警告或错误。 tsc 代码没有任何问题,我在开发人员中没有收到任何消息 Chrome或Firefox上的控制台。

更新

我尝试了combineLatest,但它仍然没有在控制台中显示任何内容。我一定错过了什么,但我不确定是什么。他们个人工作。

Observable.combineLatest( db.cassette_designs, db.glass, ( cassettes: CassetteData[], glass: GlassData[] ): void => {
  console.log( cassettes ); // doesn't print
  console.log( glass     ); // deson't print
});

可观察量以下列方式创建:

...

public Listen( event: string ): Observable<Response>
{
  return new Observable<Response>( ( subscriber: Subscriber<Response> ): Subscription => {
    const listen_func = ( res: Response ): void => subscriber.next( res );

    this._socket.on( event, listen_func );

    return new Subscription( (): void =>
      this._socket.removeListener( event, listen_func ) );
  });
}

...

然后,为了实际获得可观察量,我发送了一个关于相关事件的回复。 e.g。

...

public cassette_designs: Observable<CassetteData[]>;

...

this.cassette_designs = _socket.Listen( "get_cassette_designs" )
    .map( ( res: Response ) => res.data.data );

6 个答案:

答案 0 :(得分:9)

通过实际订阅结果,我设法让combineLatest工作 观察到。

最初我这样做了:

Observable.combineLatest( db.cassette_designs, db.glass, ( cassettes: CassetteData[], glass: GlassData[] ): void => {
  console.log( cassettes );
  console.log( glass     );
});

现在我正在这样做:

Observable.combineLatest( db.cassette_designs, db.glass ).subscribe( ( data: any[] ): void => {
  console.log( data );
  // cassettes - data[0]
  // glass     - data[1]
});

答案 1 :(得分:6)

跟进你的发现:

1)Observable是一种惰性执行数据类型,这意味着它在订阅之前不会执行管道中的任何内容。这也适用于组合运算符。 zipforkJoincombineLatestwithLatestFrom都将以递归方式订阅仅在之后传递Observables有订阅。

因此:

var output = Observable.combinelatest(stream1, stream2, (x, y) => ({x, y}));

在致电output.subscribe()之前,实际上不会做任何事情,此时subscribestream1上也会调用stream2,您将获得Rx的所有魔力。

2)更小的一点,但每当你开始做自己的创作方法时,首先看一下文档,看看它是否已经存在。有静态创建方法,ArraysPromises,节点式回调,甚至标准event patterns

因此,您的Listen方法可以变为:

public Listen<R>(event: string): Observable<R> {
  return Observable.fromEvent(this._socket, event);
}

答案 2 :(得分:1)

如果你想要一个发出2个来源的组合数据的单一流(可观察),请查看combineLatest方法。

答案 3 :(得分:1)

他们两个:Observable.zip和Observable.forkJoin必须工作。 (就个人而言,我更喜欢&#39; forkJoin&#39; - 它会返回一个具有相同顺序的数组,因为你推动了observable,并且你不需要大量的参数)

也许,如果你手动创建observable(Observable.create ......),你就忘了打电话完成&#39;对于两个提供的观察者来说,创造&#39;方法

答案 4 :(得分:0)

我使用了 combineLatest 。我需要三个 API 调用,但我只想要一个对象组合三个响应。

我遵循了同一篇文章中提到的公式:

var output = Observable.combinelatest(stream1, stream2, (x, y) => ({x, y}));

成为最终代码:

getGobalStats(): Observable<any> {

    let obs1 = this._http.get(this._config.getGlobalStatsUrl(), this._config.getOptions())
      .map((res: Response) => {
        return res.json().content;
      })
      .catch((error: any) => { console.error(error); return error; });
    let obs2 = this._http.get(this._config.getGlobalStatsUrl() + '?type=1', this._config.getOptions())
      .map((res: Response) => {
        return res.json().content;
      })
      .catch((error: any) => { console.error(error); return error; });
    let obs3 = this._http.get(this._config.getGlobalStatsUrl() + '?type=3', this._config.getOptions())
      .map((res: Response) => {
        return res.json().content;
      })
      .catch((error: any) => { console.error(error); return error; });

      return Observable.combineLatest(obs1,obs2,obs3,(res1,res2,res3) => { return {all:res1,running: res2, cycling: res3}});
  }

答案 5 :(得分:0)

        Observable.merge(
            Observable.fromEvent(canvasEl, 'mousedown'), Observable.fromEvent(canvasEl, 'touchstart'))
            .switchMap((e) => {
                return Observable.merge(
                    Observable.fromEvent(canvasEl, 'mousemove').takeUntil(Observable.fromEvent(canvasEl, 'mouseup')),
                    Observable.fromEvent(canvasEl, 'touchmove').takeUntil(Observable.fromEvent(canvasEl, 'touchend')),
                )
                    .pairwise()
            })
            .subscribe(...