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
Angular2 Merging observables
提问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
zip
and forkJoin
since they looked the most like what I wanted to do, but
nothing would work with them either.
这看起来有点傻,所以我在谷歌上搜索,看看是否有更好的方法来组合可观察值,结果发现有一些。我尝试过
zip
,forkJoin
因为它们看起来最像我想做的事情,但它们也不起作用。
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. tsc
doesn'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 combineLatest
to 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 Observable
is 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 withLatestFrom
will all recursively subscribe to the Observables
that 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 subscribe
is also called on stream1
and stream2
and you get all the magic of Rx.
直到调用实际上并不会做任何事情output.subscribe()
,在这一点subscribe
也被称为上stream1
和stream2
,你会得到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 Listen
method 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 combineLatest
method.
嘿,如果你想要一个单一的流(可观察的)来发出 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(...