我有一个服务,该服务调用API以返回可观察的Observable<MeasuringPoint[]>
我希望能够为该服务的结果订阅多个变量。每个变量MeasurementPoints $,MeasuringPointsViewed $,LatestReadings $都需要相同的数据,但是解析方式会有所不同。他们还需要彼此不了解。
有什么最佳方法的想法吗?
答案 0 :(得分:0)
所以我过去所做的就是创建一个RXJS存储,任何组件都可以注入并使用数据结果。
some-data-store.service.ts
export class SomeDataStoreService {
// Create a behavior subject that can be changed at will, always houses the "current" value.
// Allows you to always get the latest emmited value.
private _measuringPoint = new BehaviorSubject<MeasuringPoint[]>(null);
// Expose the BeahviorSubject as an observable
measuringPoint: Observable<MeasuringPoint[]> = this._measuringPoint.asObservable();
// Inject your api service
constructor(private measuringPointApi: MeasuringPointApiService) {}
//Use Api to populate Behavior subject
getMeasuringPoint() {
this.measuringPointApi
.getMeasuringPoint()
.subscribe(data => this._measuringPoint.next(data));
}
}
some-consumer.component.ts
export class SomeConsumerComponent implements OnInit {
MeasuringPoints$: MeasuringPoint[];
// Inject the DataStoreService
constructor(private someDataStore: SomeDataStoreService) {}
ngOnInit() {
// Request the data initially
this.someDataStore.getMeasuringPoint();
// Subscribe to the public member measuringPoint of the dataStoreService.
// NOTE: You can use this piece over and over in different components, they'll just fire off whenever data is changed.
this.someDataStore
.measuringPoint()
.subscribe(data => (this.MeasuringPoints$ = data));
}
}
这只是一个示例,您显然需要导入而不需要导入,但这应该可以使您朝正确的方向前进。当然,还有其他方法可以使用,例如NGRX react mui library,但是它是完整的状态管理库。我建议您进行更多研究,然后再研究是否需要像NGRX一样强大的功能。
答案 1 :(得分:0)
我想到了这样的东西:
export class ConsumerComponent implements OnInit {
mesuringPoint$: Observable<MesurePointModel>;
mesuringPointView$: Observable<MesurePointModelView>;
latestReadings$: Observable<number>;
constructor(private service: DataStoreService) {
this.mesuringPoint$ = this.service.getData().pipe(// rxjs operators);
this.mesuringPointView$ = this.service.getData().pipe(// rxjs operators );
this.latestReadings$ = this.service.getData().pipe( // rxjs operators );
ngOnInit() {
// Subscribe here or anywhere else to your observables
this.latestReadings$.subscribe(latestReadings => // number of latest readings)
}
}
重要的部分是使用RXJS转换或合并运算符,以便您可以创建将服务的可观察值作为输入的新可观察值,然后将其通过管道传递,从而创建自己的服务。
答案 2 :(得分:0)
我以前是通过以下方式完成此操作的。就像Budhead2004所说的那样,您绝对应该做一些研究,找到适合您需要的良好状态管理解决方案。我自己稍微采用了这种方法,但是对于较小的应用程序或代码段,它可以完成工作。
下面是一个正在运行的堆栈闪电战:https://stackblitz.com/edit/angular-7gjfgt
store.service.ts 管理数据状态,并将MeasuringPoints
的数组映射到每个点的单个可观察对象。
store.service.ts
import { Injectable } from '@angular/core';
import { Subject, BehaviorSubject, Observable, from } from 'rxjs';
import { mergeMap, tap } from 'rxjs/operators'
import { MeasuringPoint } from './measuring-point';
const STUB_DATA: MeasuringPoint[] = [
{ data: 'fake data 1' },
{ data: 'fake data 2' },
{ data: 'fake data 3' },
];
@Injectable({ providedIn: 'root' })
export class StoreService {
// If you receive the data as an array, you will want to store it as an array
private _subject: Subject<MeasuringPoint[]> = new BehaviorSubject([]);
// Simple state management. Could switch this out for
// a caching library or NGRX
private loadedData: boolean = false;
constructor(/* inject needed services (ie. http, etc) */) { }
// Return single MeasuringPoint objects
public getAllMeasuringPoints$(): Observable<MeasuringPoint> {
// If you haven't loaded the data yet, load it now
if (!this.loadedData) {
this._subject.next(STUB_DATA);
this.loadedData = true;
}
return this._subject
// return the observable and not the subject
.asObservable()
// Convert the array of MeasuringPoints to emit for each
// value in the array
.pipe(
// Log values for demonstration
tap((values: MeasuringPoint[]) => console.log('Values before mapping: ', values)),
// convert an observable of an array to individual observables
mergeMap((points: MeasuringPoint[]) => from(points)),
// Log values for demonstration
tap((value: MeasuringPoint) => console.log('Values after mapping: ', value)),
);
}
}
然后您可以订阅公开的方法来获取数据。任何组件都可以订阅它。由于它是BehaviorSubject
,因此订户将始终获得最新的发射值。关于BehaviorSubject
的另一点要注意的是,由于 store.service 中的可观察对象从未完成,因此您的组件在销毁后将需要取消订阅。否则,您将在整个应用程序中发生内存泄漏。
first-component.component.ts -注意: second-component.component.ts 几乎是此重复 < / p>
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs';
import { StoreService } from './store.service';
import { takeUntil } from 'rxjs/operators';
import { MeasuringPoint } from './measuring-point';
@Component({
selector: 'app-first-component',
template: `
<h3>First Component</h3>
<div *ngFor="let point of measuringPoints">
{{point | json}}
</div>
`
})
export class FirstComponentComponent implements OnInit, OnDestroy {
public measuringPoints: MeasuringPoint[] = [];
// Keep track of subscriptions
private _endSubscriptions: Subject<null> = new Subject();
constructor(private _storeService: StoreService) { }
ngOnInit() {
this._storeService.getAllMeasuringPoints$()
// This is to avoid memory leaks by unsubscribing when your component destroys
.pipe(takeUntil(this._endSubscriptions))
.subscribe((point: MeasuringPoint) => this.measuringPoints.push(point));
}
ngOnDestroy() {
this._endSubscriptions.next();
this._endSubscriptions.complete();
}
}
以下是RxJS from()
:https://www.learnrxjs.io/operators/creation/from.html
这应该给您想要的结果。让我知道是否可以。干杯!