rxjs / angular - как объединить нормализованные данные из сервиса? - PullRequest
0 голосов
/ 08 октября 2019

Я новичок в Angular и RXJS - я пытаюсь вернуть нормализованные данные из остальных API и собрать иерархию на клиенте. Я создал этот блиц стека, который является действительно базовой версией того, что я пытаюсь выполнить: https://stackblitz.com/edit/angular-ffdbza

Эти интерфейсы (ParentData, AssnData и ChildData) представляют данные JSON, возвращаемые изAPI. Интерфейсы Parent и Child - это способ, которым я хочу, чтобы данные были представлены на клиенте (в реальном приложении я привяжу этот новый объект к иерархической сетке). Ключевым моментом является то, что данные Assn имеют атрибут (statusCode), который необходимо применять к каждому дочернему элементу на основе родительского элемента.

// represents normalized data coming from the service
export interface ParentData {
  parentCode: string, 
  name: string
}

export interface AssnData {
  parentCode: string
  childId: number,
  statusCode: string
}

export interface ChildData {
  childId: number,
  type: string
}

// represents the merged data for display 
export interface Parent {
  parentCode: string,
  name: string
  kids: Child[]
}

export interface Child {
  childId: number
  type: string,
  statusCode: string
}

Это код, который у меня есть до сих пор (взят из data.component.ц в стеке блиц). Это добавляет объекты Assn к правильному родителю, но у меня возникают проблемы при объединении объекта Child с каждым объектом Assn. Я делаю console.log, чтобы увидеть результаты.

  getRelationalData() {
    let x = combineLatest(
      this.parentData$,
      this.assnData$,
      this.childData$
    ).pipe(
      map(([pData, aData, cData]) => {
        return pData.map(p => {
          return {
            ...p,
            kids: aData.filter(a => a.parentCode === p.parentCode)
          }
        })
      })
    )
    return x;
  }

1 Ответ

0 голосов
/ 08 октября 2019

У меня есть новый блик стека, который работает, но он не выглядит как самый элегантный код: https://stackblitz.com/edit/angular-rg6q5d?file=src/app/data.component.ts

Я также изменил вывод, чтобы показать JSON до / после на экране:сделать немного легче увидеть, что я пытаюсь сделать (надеюсь). Кто-нибудь может дать представление о том, как сделать это лучше?

getRelationalData() {
    let x = combineLatest(
      this.parentData$,
      this.assnData$,
      this.childData$
    ).pipe(
      map(([pData, aData, cData]) => {
        return pData.map(p => {
          // get assn objects for this parent
          let assn = aData.filter(a => a.parentCode === p.parentCode);

          // get kids for this parent based on assn object (filter undefined)
          let kids = cData.map(c => this.mergeData(c, assn))
            .filter(k => k !== undefined ) ;

          // return a new parent with the newly created child objects
          return {
            ...p,
            kids: kids
          }
        })
      })
      //, tap(x => console.log(x))
    )
    return x;
  }

  mergeData(child, assnObs){
    // filter the assn objects for each child
    let assn = assnObs.find(a => a.childId === child.id);

    // return undefined so it can be filtered later
    if (assn === undefined){
      return assn;
    }

    //return the child object with the appropriate statusCode
    return Object.assign(
      {},
      child,
      {
        statusCode: assn.statusCode
      }
    )
  }

Результирующий JSON - родительский и дочерний объекты правильно связаны друг с другом, и каждый дочерний элемент имеет соответствующий statusCode на основе родительского элемента:

[
  {
    "parentCode": "abc",
    "name": "John",
    "kids": [
      {
        "id": "123",
        "name": "Billy",
        "age": "10",
        "statusCode": "tallest"
      },
      {
        "id": "789",
        "name": "Sue",
        "age": "6",
        "statusCode": "youngest"
      }
    ]
  },
  {
    "parentCode": "xyz",
    "name": "Jane",
    "kids": [
      {
        "id": "456",
        "name": "Bobby",
        "age": "8",
        "statusCode": "something"
      },
      {
        "id": "789",
        "name": "Sue",
        "age": "6",
        "statusCode": "whatever"
      }
    ]
  }
]
...