Angular2 объединение наблюдаемых
у меня проблемы с некоторыми наблюдаемыми. Кажется, я не могу получить два. наблюдаемых в хорошее место вместе. Они прекрасно работают сами по себе, но я нужны оба значения.
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, чтобы узнать, есть ли
лучший способ объединить наблюдаемые, и оказывается, их несколько. Я попытался
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
});
это может быть что-то простое, поскольку я не вызываю функции правильно, но
Я бы подумал, что в какой-то момент я получу какое-то предупреждение или ошибку. 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 ) );
});
}
...
затем, чтобы фактически получить наблюдаемые, я отправляю прослушивание ответов на соответствующее событие. например,
...
public cassette_designs: Observable<CassetteData[]>;
...
this.cassette_designs = _socket.Listen( "get_cassette_designs" )
.map( ( res: Response ) => res.data.data );
6 ответов
мне удалось получить 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) An Observable
является ленивым типом данных выполнения, это означает, что он ничего не будет выполнять в конвейере, пока не будет подписан. Это относится и к комбинаторным операторам. zip
, forkJoin
, combineLatest
и withLatestFrom
все будут рекурсивно подписываться на Observables
что вы проходите их только после у них самих есть подписка.
отсюда:
var output = Observable.combinelatest(stream1, stream2, (x, y) => ({x, y}));
на самом деле не сделает все что угодно, пока вы не позвоните output.subscribe()
, после чего subscribe
также призвал stream1
и stream2
и вы получаете всю магию Rx.
2) более незначительный момент, но всякий раз, когда вы начинаете делать свои собственные методы создания, сначала посмотрите на документацию, чтобы увидеть, существует ли она уже. Существуют статические методы создания для,Arrays
, Promises
, обратные вызовы в стиле узла и да даже стандартные узоры событие.
Listen
метод может станьте:
public Listen<R>(event: string): Observable<R> {
return Observable.fromEvent(this._socket, event);
}
Эй, если вы хотите иметь один поток (наблюдаемый), который испускает данные комбинации из 2 источников, проверьте combineLatest
метод.
как наблюдаемые.zip и наблюдаемый.forkJoin должны работать. (Лично я предпочитаю "forkJoin" - он возвращает массив с тем же порядком, что и вы, когда вы нажимаете наблюдаемые, и вам не нужно много аргументов)
возможно, если вы создаете наблюдаемые вручную (Observable.создавать...), вы просто забыли вызвать "завершено" для обоих предоставленных наблюдателей из метода "create".
я использовал 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}});
}
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(...