TypeScript를 사용하여 RxJS의 flatMap,mergeMap,toArray 조작부호를 이해

10261 단어 rxjstypescriptwebdev
RxJS는 현재 유행하는 라이브러리로 각종 응용 프로그램에 광범위하게 응용되고 있다.그것은 심지어 Angular 등 유행 틀의 일부가 되었다.
말하지 않아도 이 라이브러리는 많은 기능이 강한 함수를 덧붙였는데, 그것들은 함께 사용할 수 있고, 몇 줄의 코드만 있으면 복잡한 문제를 해결할 수 있다.며칠 전에 개발자 사이트에서 다음과 같은 질문을 봤습니다.

How can you use flatMap operator to process a list of data as an Observable and then process the data one by one as Observables too?


물론 몇 가지 방법으로 이 문제를 해결할 수 있다.그러나 우리는 반응적인 사고방식으로 해결 방안을 해결하여 많은 유사한 문제에 사용할 수 있는 해결 방안을 제시할 것이다.

문제.


만약 응용 프로그램을 구축하고 있다면, 이 프로그램은 사용자와 각자의 주소를 표시하기 위해 일련의 비동기 호출을 처리해야 합니다.

그러나 현실 세계에서 시스템은 RESTful 서비스를 제공하여 사용자 목록을 얻을 수 있다(즉getUsers().

그런 다음 이전 사용자의 주소를 가져오려면 다른 HTTP 호출을 실행해야 합니다 (예: getAddress(userId).

RxJS 연산자와 TypeScript를 사용하여 이 문제를 수동적으로 해결하겠습니다.

정의 데이터 모델


TypeScript 인터페이스와 강력한 정적 유형으로 모델을 준비합니다.
// user.ts
export interface User {
  id: number;
  name: string;
  address?: Address;
}
사용자 인터페이스는 address 속성을 선택 사항으로 정의합니다.이것은 사용자가 유효한 주소 값을 포함하지 않았다면 undefined 이 될 수 있다는 것을 의미한다.
// address.ts
export interface Address {
  country: string;
  state: string;
  city: string;
  street: string;
  zipCode: number;
}
주소 인터페이스에는 전체 주소를 나타내는 속성 세트가 표시됩니다.

데이터 예


테스트를 간소화하기 위해서 모델에 정의된 실체에 데이터 집합을 정의합니다.
// index.t

import { Address, User } from "./address";
import { User } from "./user";

const users: User[] = [
  {
    id: 0,
    name: "Donald Mayfield"
  },
  {
    id: 1,
    name: "Jill J. Fritz"
  },
  {
    id: 2,
    name: "Terry Buttram"
  }
];

const address: Address[] = [
  {
    street: "2180 BELLFLOWER",
    country: "USA",
    state: "AL",
    city: "Madison",
    zipCode: 35064
  },
  {
    street: "845 ODOM ROAD, SUITE 200",
    country: "USA",
    state: "CA",
    city: "Los Angeles",
    zipCode: 90720
  },
  {
    street: "9025 QUEENS BLVD",
    country: "USA",
    state: "NY",
    city: "Queens",
    zipCode: 11355
  }
];
사용자 식별자의 주소를 얻기 위해 함수가 필요할 것 같습니다.
// index.ts
const getAddress = (userId: number): Observable<Address> => of(address[userId]);
앞의 함수 getAddress 는 하나의 주소를 관찰 대상으로 되돌려줍니다. Observable<Address>RxJS의 of 연산자를 사용하면 이 점을 실현할 수 있다. 이것은'연산자 만들기'로 매개 변수Address 대상)를 관찰 가능한 서열로 전환하는 데 사용된다.
현실 장면에서 비동기적인 조작은 요구에 따라 변화하는 시간을 필요로 할 수 있다.따라서, 우리는 모든 요청에 무작위 지연을 추가해서 이런 상황을 시뮬레이션할 것이다.
// index.ts
const getAddress = (userId: number): Observable<Address> =>
  of(address[userId]).pipe(
    tap(() => console.log(`getAddress(${userId})]. Started`)),
    delay(randomDelay()),
    tap(() => console.log(`getAddress(${userId}). Finished`))
  );
function 키워드가 JavaScript의 friend인 경우 다음과 같이 작성할 수 있습니다.
// index.ts
function getAddress(userId: number): Observable<Address> {
  return of(address[userId]).pipe(
    tap(() => console.log(`getAddress(${userId})]. Started`)),
    delay(randomDelay()),
    tap(() => console.log(`getAddress(${userId}). Finished`))
  );
}

데이터를 관찰 가능한 데이터로 처리하다


데이터 모델을 정의했기 때문에 이제는 사용자와 주소 그룹을 관찰 대상으로 포함할 수 있는 변수를 만들 때가 되었다.
// index.ts

let users$: Observable<User[]>;
let address$: Observable<Address[]>;
다음으로는 users$ 변수에 적절한 값을 지정합니다.
users$ = of(users);
마찬가지로 앞줄에서 of 조작부호를 사용하여 users 수조에서 관찰할 수 있는 것을 만듭니다.
현실 세계에서 '사용자' 데이터는 RESTful 단점, JSON 파일 또는 다른 비동기 호출을 실행할 수 있는 함수에서 나온다.이 함수의 결과를 관찰할 수 있기를 기대할 수도 있고, RxJS 조작부호를 사용하여 만들 수도 있습니다.

flatMap 및 mergeMap 연산자 사용


이 그룹의 사용자를 처리하고 사용자마다 getAddress(id) 호출할 때입니다.
// index.ts

address$ = users$.pipe(
  // "flat" the Array: User[] -> User
  flatMap(users => users)
);
지금 무슨 일이 일어났는지 묘사해 봅시다.

  • 사용자 달러.파이프().이 함수 호출은 RxJS 연산자(선행flatMap 연산자)를 함께 사용할 수 있는 읽을 수 있는 방법을 제공합니다.

  • flatMap() 연산자는 관찰가능User[]으로부터의 데이터 배열Observable<User[]>을 처리할 수 있습니다.또한 이 조작부호는 단일 관측 대상이 보낸 사용자를 여러 관측 대상(사용자마다 하나)으로 전환할 수 있다고 볼 수 있다.
  • 지금까지 우리는 각각 모든 사용자를 처리할 수 있다.그러나 우리는 아직 새로운 관측치로 쓸모 있는 일을 하지 않았다.각 사용자를 매핑하고 새 요청을 수행하여 주소를 찾습니다.
    // index.ts
    
    address$ = users$.pipe(
      flatMap(users => users),
      // process the User and return the Address as an Observable
      mergeMap(user => {
        const address$: Observable<Address> = getAddress(user.id);
        // You can even apply other operators to address$ here...
        return address$;
      })
    );
    

  • mergeMap() 연산자는 이전 연산자(flatMap)에서 사용자 출력을 가져옵니다.해당 주소를 가져오는 요청을 실행하기 위해 사용자 식별자를 읽습니다.이해한 바와 같이, 이 조작부호는 모든 값을 관찰할 수 있는 대상에 비추어 줍니다.
  • 이 솔루션에서 mergeMap 연산자를 사용하는 몇 가지 이유는 다음과 같습니다.
  • 우리는 한 그룹의 사용자가 있기 때문에 모든 사용자의 주소를 얻어야 한다.
  • 최종 결과의 순서는 중요하지 않다.
  • 마지막 단계로서, 당신은 다음과 같은 방식으로 구독해야 합니다.
    // Subscription
    address$.subscribe((address: Address[]) => {
      console.log({ address });
    });
    
    이 코드를 실행하면 다음과 같은 출력이 나타날 수 있습니다.
    getAddress(0)]. Started
    getAddress(1)]. Started
    getAddress(2)]. Started
    getAddress(1). Finished
    {address: {…}}
    getAddress(2). Finished
    {address: {…}}
    getAddress(0). Finished
    {address: {…}}
    
    서프라이즈!우리는 한 번에 물체 하나만 얻을 수 있다.이것은 완전히 예상한 것이다. 왜냐하면 우리는 원시 진열을 평평하게 펴고 mergeMap 조작부호를 한 번에 가시광선을 발사하기 때문이다.

    We got an initial array as an input: how can we get an array as an output?


    이것은 너희들의 현재 문제 중의 하나가 될 것이다.toArray 연산자를 사용하여 코드를 변경합니다.
    // index.ts
    
    address$ = users$.pipe(
      flatMap(users => users),
      mergeMap(user => {
        const address$: Observable<Address> = getAddress(user.id);
        return address$;
      }),
      // Get the values inside an array at the end
      toArray()
    );
    
    toArray 조작부호의 도움말 아래 원본 관측이 완료되면 모든 발사 값을 포함하는 수조 (이 예는 Address[] 를 되돌려줍니다.
    결과는 다음과 같이 JSON 객체일 수 있습니다.
    {
      "address": [
      {
        "street": "2180 BELLFLOWER",
        "country": "USA",
        "state": "AL",
        "city": "Madison",
        "zipCode": 35064
      },
      {
        "street": "845 ODOM ROAD, SUITE 200",
        "country": "USA",
        "state": "CA",
        "city": "Los Angeles",
        "zipCode": 90720
      },
      {
        "street": "9025 QUEENS BLVD",
        "country": "USA",
        "state": "NY",
        "city": "Queens",
        "zipCode": 11355
      }
    ]
    }
    

    평면지도와 합병지도


    RxJS 문서에 따르면 flatMapmergeMap의 별명이다.당신은 그것을 검증할 수 있습니다 here.
    그러나 보통 flatMap 조작부호에 대한 질문과 작업 원리에 대한 의심이 발견된다.또 얼마 전 RxJS 커뮤니티suggested renaming mergeMap 주변 사람들이 플랫맵으로 돌아왔다.
    저는 개인적으로 flatMap 조작부호를 사용하는 것을 좋아합니다. 왜냐하면 이것은 자바스크립트의 Array.prototype.flatMap() 함수와 유사하기 때문입니다.나는 그런 방식을 더 좋아한다.

    대체 솔루션


    너는 이 문제의 대체 해결 방안을 보고 싶니?Understanding switchMap and forkJoin operators in RxJS이 글을 놓치지 마세요.

    시범 공사


    실행 중인 전체 항목 찾기StackBlitz.브라우저의 콘솔을 열어 결과를 보는 것을 잊지 마세요.
    너는 계속해서 나GitHub를 주목하고 나의 일에 대해 더 많은 정보를 얻을 수 있다.
    현대 인터넷 컨설팅 회사로 기업의 디지털화 전환을 돕는 데 주력하고 있다.React, Angular, Vue, 웹 구성 요소,GraphQL,Node,Bazel 또는 Polymer에 대한 전문가 구조 지도, 교육 또는 문의는 방문thisdotlabs.com하십시오.
    이런 인터넷 매체는 모든 사람을 위해 포용성과 교육적인 네트워크를 만드는 데 전념한다.이벤트, 팟캐스트, 무료 콘텐츠를 통해 현대 인터넷의 최신 진전을 알 수 있습니다.자세한 내용은 thisdot.co를 참조하십시오.

    좋은 웹페이지 즐겨찾기