Search code examples
angularrxjsangular6rxjs6combinelatest

How to trigger again HttpGet request in Angular 6?


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

Solution

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