RxJS를 사용한 Angular의 데이터 구성

Mar 14 2023
1. 소개 이 글에서는 플랫폼의 데이터를 쉽게 처리할 수 있도록 구성하는 방법에 대해 알아봅니다.
Unsplash에 있는 Ricardo Gomez Angel의 사진

1. 소개

이 기사에서는 처리하기 쉽도록 플랫폼의 데이터를 구성하는 방법을 살펴봅니다.
학생 및 해당 클래스의 정보를 표시해야 하는 애플리케이션의 예를 들어 보겠습니다. 이 경우 여러 데이터 소스를 하나로 처리해야 합니다.

Angular에서 데이터 구성이란 무엇입니까?

간단히 말해서 데이터 구성은 조작 가능한 단일 데이터 소스를 생성하기 위해 두 개 이상의 데이터 소스를 결합하는 것으로 구성됩니다.

Firebase에 연결된 애플리케이션으로 데모를 실행할 것입니다.

2. 데이터 소스 복구

여기서 목표는 애플리케이션에 필요한 모든 데이터 소스를 얻는 것입니다.

모델

응용 프로그램의 컨텍스트를 알면 조작할 두 가지 유형의 데이터를 나타내는 두 가지 인터페이스를 만듭니다.

class.model.ts

export interface Classe {
  uid: string;
  name: string;
  titulaire: string;
  createdAt: Date;
  updatedAt: Date | null;
}

export interface Student {
  uid: string;
  name: string;
  phoneNumber: string;
  emailAddress: string;
  classe: string;
  createdAt: Date;
  updatedAt: Date | null;
}

이 서비스를 통해 학생들과 관련된 모든 정보를 수집할 수 있습니다.

import {Injectable} from '@angular/core';
import {Student} from '../models/students.model';
import {FirestoreService} from './firestore.service';
import {Observable, catchError} from 'rxjs';

@Injectable({providedIn: 'root'})
export class StudentService{
  handlerError: any = '';
  students$ = Observable<Student[]> = this.firestoreService.col$('students/')
    .pipe(
      tap(console.log),
      catchError(this.handlerError)
    );
  constructor(private firestoreService: FirestoreService){}
}

이 구성요소의 목적은 이전에 생성된 서비스에서 학생 정보를 검색하여 로컬 Students$ 속성에 저장하는 것입니다.

import {Component, OnInit} from '@angular/core';
import {catchError, of} from 'rxjs';
import {StudentService} from '../services/student.service';

export class GroupsComponent implements OnInit{
  errorMessage = '';
  students$ = this.studentService.students$
    .pipe(
      catchError((error) => {
        this.errorMessage = error;
        return of(null);
      })
    );
  constructor(private studentService: StudentService) {}
}

우리의 관점에서 우리는 관찰 가능 항목을 자동으로 구독 및 구독 취소하는 비동기 파이프를 지정하여 관찰 가능 항목에 바인딩합니다.

<div *ngIf="students$ | async as students">
    <button type="button" *ngIf='let student of students'>
      {{student.name | titlecase}} - {{student.class}}
    </button>
</div>

3. 데이터 구성

구성은 우리가 이미 수집한 데이터를 동일한 정보로 결합하는 것으로 구성됩니다.

학생 정보에는 읽을 수 없는 문자열인 클래스의 uid가 있지만 여기서 목표는 이 클래스의 정보도 검색하고 예를 들어 그의 이름을 표시하는 것입니다.

수업 의 회복은 학생들 과 같은 방식으로 이루어질 것입니다 .

class.service.ts

import {Injectable} from '@angular/core';
import {Classe} from '../models/classes.model';
import {FirestoreService} from './firestore.service';
import {Observable, catchError} from 'rxjs';

@Injectable({providedIn: 'root'})
export class ClasseService{
  handlerError: any = '';
  classes$ = Observable<Classe[]> = this.firestoreService.col$('classes/')
    .pipe(
      tap(console.log),
      catchError(this.handlerError)
    );
  constructor(private firestoreService: FirestoreService){}
}

Students.service.ts

studentsWithClasses$ = combineLatest(
    this.students$
    this.classeServices.classes$
  ).pipe(
    map(([students, classes]) => {
      return students.map(student=> ({
        ...student,
        classe: classes.find(classe => classe.uid === student.uidClasse).name
      } as Student));
    })
  );

이제 클래스 이름과 함께 학생 정보가 포함된 StudentsWithClasses$를 검색합니다 .

import {Component, OnInit} from '@angular/core';
import {catchError, of} from 'rxjs';
import {StudentService} from '../services/student.service';

export class GroupsComponent implements OnInit{
  errorMessage = '';
  students$ = this.studentService.studentsWithClasses$
    .pipe(
      catchError((error) => {
        this.errorMessage = error;
        return of(null);
      })
    );
  constructor(private studentService: StudentService) {}
}

사용자 작업에 대한 응답으로 스트림을 결합할 수도 있습니다. 이를 위해 Action Stream을 생성합니다 .

Students.service.ts

private studentSelectedAction = new BehaviorSubject<string>(null);
studentSelectedAction$ = this.studentSelectedAction.asObservable();

selectedStudent$ = combineLatest(
    this.studentSelectedAction$,
    this.studentsWithClasses$
  ).pipe(
    map(([selectedStudentUid, students]) => {
      return students.find(student => student.uid === selectedStudentUid);
      }
    )
  );

private changeSelectedStudent(selectedStudentUid: string | null): void {
  this.studentSelectedAction.next(selectedStudentUid);
}
onSelect(studentUid: string): void {
  this.changeSelectedStudent(studentUid);
}

구성 요소에는 onSelect() 메서드를 호출하는 두 가지 방법이 있습니다.

  1. 동일한 구성 요소에 있는 경우 : 작업 아래에서 메서드를 호출하는 메서드를 만듭니다.
  2. restoreStore(idStudent: string): void {
      this.studentService.onSelect(idStudent);
    }
    

    this.route.paramMap.subscribe(
      idGroup => {
        this.uidStudent = idStudent.get('idStudent');
        this.studentService.onSelect(this.idStudent);
    )
    

명확하지 않은 것이 있거나 질문이 있는 경우 주저하지 말고 의견을 말하거나 Twitter 에서 저에게 연락하십시오 .

참조:

Deborah Kurata의 RxJS를 사용한 데이터 구성 :https://www.youtube.com/watch?v=Z76QlSpYcck

PlainEnglish.io 에 더 많은 내용이 있습니다 .

무료 주간 뉴스레터를 신청하십시오 . Twitter , LinkedIn , YouTube 및 Discord 에서 팔로우하세요 .

소프트웨어 시작을 확장하는 데 관심이 있으십니까 ? 회로를 확인하십시오 .