Предотвращение манипулирования данными BehaviorSubject в компоненте отражается в сервисе - PullRequest
0 голосов
/ 18 марта 2020

Я использую общий сервис для обмена данными между различными компонентами. Проблема в том, что когда я пытаюсь использовать этот сервис внутри моего компонента и фильтрую некоторые данные, то же самое происходит и с общими данными. Как я могу предотвратить это? Я использовал оператор tap вместо карты при подписке, но он не работает. Еще одно решение, которое я попробовал, это cloneDeep из библиотеки loda sh, которая также не работает.

Shared Service

export class SharedDataService {
    private treeReport = new BehaviorSubject<ResultModel>(null);

    constructor() { }

    updateTreeReport(newReport: ResultModel) {
        this.treeReport.next(newReport);
    }

    getTreeReport() {
        return this.treeReport.asObservable();
    }
}

Компонент

this.featureDetails$ = this.sharedService.getTreeReport().pipe(map(treeReport) => {
      treeReport.features = treeReport.features.filter(item => item._id == id)
      return treeReport
    }))

Что я пробовал следующим образом

1.

this.featureDetails$ = this.sharedService.getTreeReport().pipe(tap(treeReport) => {
          treeReport.features = treeReport.features.filter(item => item._id == id)
          return treeReport
        }))

2.

this.featureDetails$ = this.sharedService.getTreeReport().pipe(map(treeReport) => {
          treeReport.features = cloneDeep(treeReport.features.filter(item => item._id == id))
          return treeReport
        }))

Ответы [ 2 ]

0 голосов
/ 18 марта 2020

Я исправил это, добавив cloneDeep в общую службу.

getTreeReport() {
    return cloneDeep(this.treeReport.asObservable());
}

Каждый раз, когда он будет возвращать клонированную копию наблюдаемой

0 голосов
/ 18 марта 2020

Проблема заключается в том, что вы изменяете эти данные, и одна и та же ссылка используется всеми потребителями.

Если вам нужен только фильтрованный массив features без повсеместного изменения данных, вы можете воспользоваться следующим подходом:

this.featureDetails$ = this.sharedService.getTreeReport().pipe(
    pluck('features'),
    map(features => features.filter(item => item._id == id))
);

pluck .

Array.prototype.filter изменит не мутирует исходный массив, но создаст новый.

Также помните, что Subject.asObservable() создает новую наблюдаемую, источником которой является сам субъект.

...