I'm using combineLatest
to merge data from websocket
and database
into one object. Each time the websocket
sends data my data are refreshing. Although I'd like to refresh data at page manually also by pressing the button. Unfortunately combineLatest
isn't detect that I made HttpGet
request to get newest data.
export class ShowTestDataComponent implements OnInit {
stockData: RootObject;
private stocksData$: WebSocketSubject<MessageEvent>;
private stocksResources$: Observable<DbObject[]>;
constructor(private stockService: StockService, private webSocketService: WebSocketServiceService) {
this.stocksData$ = this.webSocketService.connect();
this.stocksResources$ = this.stockService.getStocksResources();
}
buyStock(code, quantityToBuy): void {
const dto: DbObject = {
code: code,
quantity: quantityToBuy
};
this.stockService.buyStock(dto).pipe(
mergeMap(() => this.stockService.getStocksResources())
).subscribe((res) => this.stocksResources$ = of(res));
}
prepareStockData(): void {
combineLatest(
this.stocksData$,
this.stocksResources$,
(stockData: RootObject, stockResources: DbObject[]) => ({
stockData,
stockResources
})
).subscribe((pair) => {
this.stockData = JSON.parse(pair.stockData.data);
this.stockData.Items.forEach(item => {
item.Quantity = pair.stockResources.find(d => d.code === item.Code).quantity;
});
});
}
ngOnInit() {
this.prepareStockData();
}
}
So as you can see If I'll press BUY
on UI then method buyStock
will be executed and there are executing this.stockService.buyStock(dto)
to change data in DB, and then this.stockService.getStocksResources()
to refresh data from DB. Everything works, data are changed but data isn't refreshing (comibneLatest isn't detect any message from stocksResources$
Here is my service, I think that problem is in componenet though.
export class StockService {
apiUrl = "http://localhost:5001/api/values";
constructor(private http: HttpClient) { }
getStocksResources(): Observable<DbObject[]> {
return this.http.get<DbObject[]>(this.apiUrl + "/stocks");
}
buyStock(data: DbObject){
return this.http.post<DbObject>(this.apiUrl + "/quantity", data);
}
}
You have to create new Subject. So declare:
private stocksResources$: Subject<DbObject[]> = new Subject();
In Constructor you have to emit your received stockResources
data using your Subject
:
constructor(private stockService: StockService) {
this.stockService.getStocksResources().subscribe(res => {
this.stocksResources$.next(res);
});
}
And each time you buy new stock - you have to emit your data again.
this.stockService.buyStock(dto).pipe(
mergeMap(() => this.stockService.getStocksResources())
).subscribe((res) => {
this.stocksResources$.next(res);
});
And that's it :)
Whole code:
export class ShowTestDataComponent implements OnInit {
stockData: RootObject;
private stocksData$: WebSocketSubject<MessageEvent>;
private stocksResources$: Subject<DbObject[]> = new Subject();
constructor(private stockService: StockService, private webSocketService: WebSocketServiceService) {
this.stocksData$ = this.webSocketService.connect();
this.stockService.getStocksResources().subscribe(res => {
this.stocksResources$.next(res);
});
}
buyStock(code, quantityToBuy): void {
const dto: DbObject = {
code: code,
quantity: quantityToBuy
};
this.stockService.buyStock(dto).pipe(
mergeMap(() => this.stockService.getStocksResources())
).subscribe((res) => {
this.stocksResources$.next(res);
});
}
prepareStockData(): void {
combineLatest(
this.stocksData$,
this.stocksResources$,
(stockData: RootObject, stockResources: DbObject[]) => ({
stockData,
stockResources
})
).subscribe((pair) => {
this.stockData = JSON.parse(pair.stockData.data);
this.stockData.Items.forEach(item => {
item.Quantity = pair.stockResources.find(d => d.code === item.Code).quantity;
});
});
}
ngOnInit() {
this.prepareStockData();
}
}