简体   繁体   中英

Use Rxjs in Angular to update data in a Json coming from different Json sources

I have 3 different services A,B,C. These services produce each a different JSON. JSON from service A has properties which values need to be replaced with values from JSON B and C.

I have solved this using plain JavaScript but I want to use Rxjs, because Rxjs is scalable. And I want to return an Observable instead of data.

My three JSON's:

let A = {
    "conditions": [{
        "conditionId": "BASFD",
        "conditionDescr": "Substitute with component description",
        "pay": "P"
    }, {
        // << more items >>
    }]
};

let B = {
    "components": [{
        "componentId": "BASFD",
        "description": "Assortimentsbonus"
    }, {
        "componentId": "BBY",
        "description": "Bonus bypass"
    }]
};

let C = {
    "text": [{
        "textcode": "PAYMENT",
        "values": [{
            "code": "P",
            "description": "Percentage"
        }, {
            "code": "A",
            "description": "Amount"
        }]
    }, {
        "textcode": "PERIOD",
        "values": [{
            "code": "J",
            "description": "Per year"
        }, {
            "code": "M",
            "description": "Per month"
        }]
    }]
}

My JavaScript code to substitute the values ConditionDescr and Pay in JSON A:

this.httpClient.get<ConditieTypeObject>(environment.url + 'bonus/' + id, {
    params: new HttpParams().append('year', year.toString()),
    observe: 'body',
    responseType: 'json'
}).pipe(map(x => x.conditions)).subscribe((A) => {

    A.forEach((y) => {
        y.conditionDescr = B.components.filter(function (x2) {
            return x2.componentId == y.conditionId;
        })[0].description;

        y.pay = C.text.filter(function (x3) {
            return x3.textcode == 'PERIOD';
        })[0].values.filter(function (x4) {
            return x4.code == y.pay;
        })[0].description;
    });

    console.log(A);
});

Then the result is this and thats OK:

{
    "conditions": [{
        "conditionId": "BASFD",
        "conditionDescr": "Assortimentsbonus",
        "pay": "Per year"
    }, {
        // << more items >>
    }]
}

But I want to solve this in Rxjs because I can use an observable which can be passed directly as an async to an HTML table. I don't want to subscribe first into the function like in my code right now.

I tried it with switchMap and concatMap but that doesn't work. Anybody have an idea how to solve this in RxJS ?

You can pipe() an RxJS map() after using combineLatest to combine your three service requests into a single Observable. This Observable can then be assigned to a variable in your components class and referenced using the async pipe in your template.

In your component.ts:

import { Component, OnInit } from '@angular/core';
import * as fromServices from './services';
import { combineLatest, Observable } from 'rxjs';
import { map } from 'rxjs/operators';

export class ExampleComponent implements OnInit {
  // 1. Create a new reference for an Observable that will contain your final data.
  finalData$: Observable<any[]>;

  constructor(
    // 2. Include your various services in your component.
    private aService: fromServices.AService,
    private bService: fromServices.BService,
    private cService: fromServices.CService,
  ) {}

  ngOnInit(): void {
    // 3. Initialise the Observables from your services in an Array passed into combineLatest.
    this.finalData$ = combineLatest([
      this.aService.data$,
      this.baService.data$,
      this.cService.data$,
    ])
    // 4. Map over each Observable.
    .pipe(map(([aData, bData, cData]) => {
      // 5. Transform your data. Note: Your Observable must return a value for it to emit a value.
      return aData.filter(() => { /* ... */ });
    }));
  }
}

In your component.html:

<!-- 6. Use the async pipe to subscribe to this data. -->
<p *ngFor="let data of {{ finalData$ | async }}">{{ data.propertyName }}</p>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM