[javascript] 특정 부작용에 대한 새 구독을 언제 작성해야합니까?

지난주에 RxJS 질문에 답변 했는데 다른 커뮤니티 멤버와 “모든 특정 부작용에 대해 구독을 작성해야합니까? 아니면 일반적으로 구독을 최소화해야합니까?” 완전한 반응 형 응용 프로그램 접근 방식 또는 서로 전환하는 시점에서 사용할 방법을 알고 싶습니다. 이것은 저와 다른 사람들이 불쾌한 토론을 피하는 데 도움이 될 것입니다.

설치 정보

  • 모든 예제는 TypeScript에 있습니다.
  • 질문에 더 초점을 맞추려면 구독에 수명주기 / 생성자를 사용하지 않고 프레임 워크를 관련이 없습니다.
    • 상상해보십시오. 구독은 생성자 / 라이프 사이클 초기화에 추가됩니다.
    • 상상 : 구독 취소는 수명주기에서 완료됩니다.

부작용이란 무엇입니까 (각도 샘플)

  • 업데이트 / UI에 입력 (예 value$ | async)
  • 구성 요소의 출력 / 업스트림 (예 @Output event = event$)
  • 서로 다른 계층에서 서로 다른 서비스 간 상호 작용

예시적인 사용 사례 :

  • 두 가지 기능 : foo: () => void; bar: (arg: any) => void
  • 두 가지 관측소 : http$: Observable<any>; click$: Observable<void>
  • foohttp$방출 후 호출 되며 값이 필요하지 않습니다.
  • barclick$방출 후 호출 되지만 현재 값이 필요합니다.http$

사례 : 모든 특정 부작용에 대한 구독 생성

const foo$ = http$.pipe(
  mapTo(void 0)
);

const bar$ = http$.pipe(
  switchMap(httpValue => click$.pipe(
    mapTo(httpValue)
  )
);

foo$.subscribe(foo);
bar$.subscribe(bar);

사례 : 일반적으로 구독 최소화

http$.pipe(
  tap(() => foo()),
  switchMap(httpValue => click$.pipe(
    mapTo(httpValue )
  )
).subscribe(bar);

간단히 말해서 내 자신의 의견

구독자가 Rx 환경을 더 복잡하게 만든다는 사실을 이해할 수 있습니다. 가입자가 파이프에 영향을 미치거나 예를 들어 관찰 할 수 있는지 여부를 고려해야하기 때문입니다. 그러나 코드를 더 많이 분리할수록 (포커스가 많을수록 발생하는시기) 나중에 코드를 유지 관리 (테스트, 디버그, 업데이트)하기가 쉬워집니다. 이를 염두에두고 항상 관찰 가능한 단일 소스와 코드의 부작용에 대한 단일 구독을 만듭니다. 두 개 이상의 부작용이 정확히 동일한 소스 관찰 가능 항목에 의해 트리거되는 경우 관찰 가능 항목을 공유하고 각 부작용을 개별적으로 구독합니다. 수명주기가 다를 수 있기 때문입니다.



답변

RxJS는 비동기 작업을 관리하는 데 유용한 리소스이며 가능한 경우 코드 (구독 수 감소 포함)를 단순화하는 데 사용해야합니다. 마찬가지로 RxJS가 애플리케이션에서 전체 구독 수를 줄일 수있는 솔루션을 제공하는 경우 옵저버 블 뒤에 자동으로 해당 옵저버 블에 대한 구독이 없어야합니다.

그러나 ‘필수’가 아닌 구독을 작성하는 것이 유리한 상황이 있습니다.

예외 예-단일 템플릿에서 관찰 가능 항목 재사용

첫 번째 예를 보면 :

// Component:

this.value$ = this.store$.pipe(select(selectValue));

// Template:

<div>{{value$ | async}}</div>

value $가 템플릿에서 한 번만 사용되는 경우 비동기 파이프와 코드 절약 및 자동 가입 취소에 대한 이점을 활용합니다. 그러나이 답변 에 따라 템플릿의 동일한 비동기 변수에 대한 여러 참조는 피해야합니다.

// It works, but don't do this...

<ul *ngIf="value$ | async">
    <li *ngFor="let val of value$ | async">{{val}}</li>
</ul>

이 상황에서 대신 별도의 구독을 작성하고이를 사용하여 컴포넌트에서 비동기가 아닌 변수를 업데이트합니다.

// Component

valueSub: Subscription;
value: number[];

ngOnInit() {
    this.valueSub = this.store$.pipe(select(selectValue)).subscribe(response => this.value = response);
}

ngOnDestroy() {
    this.valueSub.unsubscribe();
}

// Template

<ul *ngIf="value">
    <li *ngFor="let val of value">{{val}}</li>
</ul>

기술적으로는 없이도 동일한 결과를 얻을 수 valueSub있지만 응용 프로그램의 요구 사항은 이것이 올바른 선택임을 의미합니다.

구독 여부를 결정하기 전에 관찰 가능 항목의 역할 및 수명 고려

둘 이상의 관측 가능 항목을 함께 사용할 때만 사용하는 경우 적절한 RxJS 연산자를 사용하여 단일 관측 값으로 결합해야합니다.

마찬가지로, first () 를 사용하여 Observable의 첫 번째 방출을 제외한 모든 것을 걸러내는 경우, 지속적인 역할을 수행하는 Observable보다 코드를 경제적으로 사용하고 ‘추가’구독을 피해야 할 더 큰 이유가 있다고 생각합니다. 세션.

개별 옵저버 블 중 하나가 다른 옵저버 블과 독립적으로 유용한 경우 별도의 구독 (들)의 유연성과 명확성을 고려할 가치가 있습니다. 그러나 초기 진술에 따라 명확한 이유가없는 한 모든 관찰 가능 항목에 대해 구독을 자동으로 생성해서는 안됩니다.

수신 거부 관련 :

추가 구독 대한 요점 은 더 많은 구독 취소 가 필요하다는 것입니다. 말씀 드린대로, 필요한 모든 탈퇴가 Destroy에 적용되었다고 가정하고 싶지만 실제 생활이 항상 그렇게 원활하게 진행되는 것은 아닙니다! 다시, RxJS는 이 프로세스를 간소화 하는 유용한 도구 (예 : first () )를 제공하여 코드를 단순화하고 메모리 누수 가능성을 줄입니다. 이 기사 에서는 유용한 추가 정보와 예제를 제공합니다.

개인 취향 / 상세와 간결함 :

자신의 취향을 고려하십시오. 코드의 세부 정보에 대한 일반적인 토론을하고 싶지는 않지만 너무 많은 ‘노이즈’와 코드를 지나치게 암호로 만드는 것 사이의 적절한 균형을 찾는 것이 목표입니다. 이것은 가치가있을 수 있습니다 .


답변

구독 최적화가 최종 게임이라면 논리적 인 극단으로 가서 다음과 같은 일반적인 패턴을 따르십시오.

 const obs1$ = src1$.pipe(tap(effect1))
 const obs2$ = src2$pipe(tap(effect2))
 merge(obs1$, obs2$).subscribe()

탭에서 독점적으로 부작용을 실행하고 병합을 사용하여 활성화하면 구독이 하나만 있음을 의미합니다.

이것을하지 않는 한 가지 이유는 RxJS를 유용하게 만드는 많은 것들을 중립화하고 있기 때문입니다. 관찰 가능한 스트림을 작성하고 필요에 따라 스트림을 구독 / 구독 해제하는 기능입니다.

나는 관찰 가능 항목이 논리적으로 구성되어 있고 구독 감소라는 이름으로 오염되거나 혼동되어서는 안된다고 주장합니다. foo 효과를 논리적으로 bar 효과와 결합해야합니까? 하나는 다른 하나를 필요로합니까? http $가 발생할 때 foo 트리거를 원하지 않을 것입니까? 관련없는 기능간에 불필요한 연결을 생성하고 있습니까? 이것들은 모두 하나의 스트림에 넣지 않는 이유입니다.

이것은 여러 구독 IMO로 관리하기 쉬운 오류 처리를 고려하지 않아도됩니다.


답변