typescript Angular2 合并 observables

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/38376170/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 03:39:25  来源:igfitidea点击:

Angular2 Merging observables

typescriptangularrxjs

提问by Hector

I'm having trouble getting with some observables. I can't seem to get two observables to place nice together. They work just fine on their own, but I need both values.

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

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

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

Not being all that familiar with observables, the first thing I tried was nesting one inside the other, but the inner one doesn't seem to do anything.

对 observables 不太熟悉,我尝试的第一件事是将一个嵌套在另一个中,但内部的似乎没有做任何事情。

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

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

This seemed a bit silly to be so I searched on Google to see if there was a better way to combine observables and it turns out there are a few. I tried zipand forkJoinsince they looked the most like what I wanted to do, but nothing would work with them either.

这看起来有点傻,所以我在谷歌上搜索,看看是否有更好的方法来组合可观察值,结果发现有一些。我尝试过 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
});

It could be something as simple as I'm not calling the functions correctly, but I'd have thought I would get some sort of warning or error at some point. tscdoesn't have any problem with the code and I get no messages in the developer consoles on either Chrome or Firefox.

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

Update

更新

I've tried combineLatest, but it still doesn't display anything in the console. I must be missing something, but I'm not sure what. They work individually.

我试过了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
});

The observables are create in the following way:

可观察对象的创建方式如下:

...

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 ) );
  });
}

...

Then to actually get the observables I send a listen for responses on the relevant event. e.g.

然后为了实际获得可观察值,我发送了对相关事件的响应的监听。例如

...

public cassette_designs: Observable<CassetteData[]>;

...

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

回答by Hector

I managed to get combineLatestto work, by actually subscribing to the resulting observable.

combineLatest通过实际订阅生成的 observable,我设法开始工作。

Originally I was doing this:

本来我是这样做的:

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

Now I'm doing this:

现在我这样做:

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

回答by paulpdaniels

To follow up with your findings:

要跟进您的发现:

1) An Observableis a lazy execution data type, this means that it will not execute anything in the pipeline until it is subscribed to. This goes for the combinatorial operators as well. zip, forkJoin, combineLatest, and withLatestFromwill all recursively subscribe to the Observablesthat you pass them only afterthey themselves have subscriptions.

1) AnObservable是惰性执行数据类型,这意味着它在订阅之前不会执行管道中的任何内容。这也适用于组合运算符。zip, forkJoin, combineLatest, 和withLatestFrom都将递归订阅Observables您传递给他们的 ,只有他们自己有订阅之后。

Hence:

因此:

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

Won't actually do anything until you call output.subscribe(), at which point subscribeis also called on stream1and stream2and you get all the magic of Rx.

直到调用实际上并不会做任何事情output.subscribe(),在这一点subscribe也被称为上stream1stream2,你会得到Rx的所有魔法。

2) A more minor point but whenever you start doing your own creation methods, have a look first at the documentation to see if it already exists. There are static creation methods for, Arrays, Promises, Node-style callbacks and yes even standard event patterns.

2) 一个更次要的点,但是每当您开始使用自己的创建方法时,请先查看文档以查看它是否已经存在。有用于, Arrays, Promises, Node 风格的回调的静态创建方法,是的,甚至是标准的事件模式

Thus your Listenmethod can become:

因此你的Listen方法可以变成:

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

回答by Harry Ninh

Hey if you want to have a single stream (observable) that emits a combination data of the 2 sources, check out combineLatestmethod.

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

回答by Oleg Barinov

Both of them: Observable.zip and Observable.forkJoin must work. (Personally, I prefer 'forkJoin' - it returns an array with the same order, as you pushed observables, and you don't need a plenty of arguments)

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

Maybe, if you are creating observables manually (Observable.create...), you just forgot to call 'completed' for both provided Observers from 'create' method.

也许,如果您手动创建 observables (Observable.create...),您只是忘记为来自 'create' 方法的两个提供的 Observer 调用 'completed'。

回答by Pere Pages

I've used combineLatest. I needed three APIcalls, but I wanted only one Object combining the three responses.

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

I've followed to formula mentioned in this same post:

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

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

Being the final code:

作为最终代码:

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}});
  }

回答by LastTribunal

        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(...