【问题标题】:Use Rxjs in Angular to update data in a Json coming from different Json sources在 Angular 中使用 Rxjs 更新来自不同 Json 源的 Json 中的数据
【发布时间】:2019-12-23 20:49:01
【问题描述】:

我有 3 种不同的服务 A、B、C。这些服务各自生成不同的 JSON。来自服务 A 的 JSON 具有需要用来自 JSON B 和 C 的值替换的属性。

我已经使用纯 JavaScript 解决了这个问题,但我想使用 Rxjs,因为 Rxjs 是可扩展的。我想返回一个 Observable 而不是数据。

我的三个 JSON:

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"
        }]
    }]
}

我的 JavaScript 代码用于替换 JSON A 中的值 ConditionDescrPay

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

那么结果就是这样,那样就OK了:

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

但我想在 Rxjs 中解决这个问题,因为我可以使用一个 observable,它可以直接作为异步传递给 HTML 表。我不想像现在在我的代码中那样先订阅该函数。

我用switchMapconcatMap 尝试过,但不起作用。有人知道如何在 RxJS 中解决这个问题吗?

【问题讨论】:

    标签: javascript node.js angular rxjs observable


    【解决方案1】:

    您可以在使用combineLatest 将您的三个服务请求组合成一个 Observable 之后,pipe() 和 RxJS map()。然后可以将此 Observable 分配给组件类中的变量,并使用模板中的异步管道进行引用。

    在您的 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(() => { /* ... */ });
        }));
      }
    }
    

    在您的 component.html 中:

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

    【讨论】:

    • 您好安德鲁,感谢您的回答。但这并不能解决问题,因为我仍然需要订阅,这打破了可观察的 rxjs 模式。我想返回一个 observable。
    • 要访问 observable 中的数据,您必须订阅该 observable。我很好奇为什么你认为订阅的需要打破了可观察的模式?
    • 在我的 HTML 代码中,我想用异步进行订阅,如果我以你的例子为例,它看起来像这样: [value]="finalData | async" 在这种情况下,finalData 是一个 Observable而不是一个数组。然后我也不需要取消订阅,因为它是由 HTML 组件完成的。
    • @Ben - 我明白了。您可以在 combineLatest 之后 pipe 和 RxJS map 来根据需要转换数据。这可以全部分配给组件类中的变量,然后使用异步管道进行引用。查看更新的答案。
    • 嗨 Andrew,我更新了你的代码,并在转换部分实现了我的转换代码,但如果我订阅测试,那么它给出了一个未定义的结果。你能看一下吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-02
    • 2020-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多