source

테이크(1) 대 퍼스트 클래스

nicesource 2023. 6. 3. 08:32
반응형

테이크(1) 대 퍼스트 클래스

의 몇 가지 구현을 찾았습니다.AuthGuard그것을 사용자take(1)내 프로젝트에서, 나는 사용했습니다.first().

둘 다 같은 방식으로 작동합니까?

import 'rxjs/add/operator/map';
import 'rxjs/add/operator/first';
import { Observable } from 'rxjs/Observable';

import { Injectable } from '@angular/core';
import { CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { AngularFire } from 'angularfire2';

@Injectable()
export class AuthGuard implements CanActivate {

    constructor(private angularFire: AngularFire, private router: Router) { }

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | boolean {
        return this.angularFire.auth.map(
            (auth) =>  {
                if (auth) {
                    this.router.navigate(['/dashboard']);
                    return false;
                } else {
                    return true;
                }
            }
        ).first(); // Just change this to .take(1)
    }
}

연자first()그리고.take(1)같지 않습니다.

first()인 연자는선사사용니합다을항을 사용합니다.predicate, 기하고방니다합출능을 합니다.error소스가 완료되었을 때 일치하는 값이 없을 때 알림.

예를 들어 다음과 같은 오류가 발생합니다.

import { EMPTY, range } from 'rxjs';
import { first, take } from 'rxjs/operators';

EMPTY.pipe(
  first(),
).subscribe(console.log, err => console.log('Error', err));

뿐만 아니라 다음과 같습니다.

range(1, 5).pipe(
  first(val => val > 6),
).subscribe(console.log, err => console.log('Error', err));

이 값은 처음 방출된 값과 일치합니다.

range(1, 5).pipe(
  first(),
).subscribe(console.log, err => console.log('Error', err));

에 ㅠㅠㅠtake(1)첫 번째 값을 가져와서 완료합니다.더 이상의 논리는 관여하지 않습니다.

range(1, 5).pipe(
  take(1),
).subscribe(console.log, err => console.log('Error', err));

그러면 관측 가능한 빈 소스를 사용하면 오류가 발생하지 않습니다.

EMPTY.pipe(
  take(1),
).subscribe(console.log, err => console.log('Error', err));

2019년 1월: RxJS 6용으로 업데이트됨

팁: 사만만 하세요.first()다음과 같은 경우:

  • 0개의 항목이 방출되는 것을 오류 조건(예: 방출 완료)으로 간주하고 0% 이상의 오류 가능성이 있을 경우 정상적으로 처리합니다.
  • 또는 관측 가능한 소스가 1개 이상의 항목을 방출한다는 것을 100% 알고 있습니다(따라서 절대 던질없음).

인 경우 하지 않는 배이이 0고와 0로으적처리경않우지는(with 출량함 0하명시께와이▁if함)catchError그러면 오류가 전파되어 다른 곳에서 예기치 않은 문제가 발생할 수 있으며 특히 최종 사용자가 보낸 오류일 경우 추적하기가 매우 까다로울 수 있습니다.

사용하는 이 더 안전합니다.take(1)대부분의 경우, 다음과 같은 경우:

  • 요.take(1)소스가 방출 없이 완료되면 아무것도 방출하지 않습니다.
  • 인라인 서술어를 사용할 필요가 없습니다(예: first(x => x > 10))

참고: 술어는 다음과 같이 사용할 수 있습니다.take(1)와 같이: 과같이다음:.pipe( filter(x => x > 10), take(1) )10보다 큰 .

때어는?single()

만약 당신이 더 엄격해지고 싶다면, 그리고 두 개의 배출물을 허용하지 않는다면 당신은 사용할 수 있습니다.single()0개 또는 2개 이상의 배출물이 있는 경우 어떤 오류가 발생하는지 확인합니다.이 경우에도 오류를 처리해야 합니다.

»:Single관찰 가능한 체인이 http 서비스를 두 번 호출하고 관찰 가능한 두 개를 내보내는 것과 같은 추가 작업을 수행하지 않도록 하려면 가끔 유용할 수 있습니다. 추가하기single파이프 끝까지 당신이 그런 실수를 했는지 알려줄 것입니다.러너'에서에 '태스크 러너'를 답을 합니다.single(), catchError()좋은 행동을 보장하기 위해.


항상사지이유를 사용하지 ?first()take(1)?

아. 게떻. 어게.first 잠재적으로 더 많은 오류를 유발할 수 있습니까?

서비스에서 무언가를 가져온 다음 파이프로 연결하는 관찰 가능한 항목이 있는 경우first()당신은 대부분 잘 지내야 합니다. 어떤를 비활성화하기 - 을 방출하기 한다면,of(null)또는NEVER그 다음에는 아무 하류나.first()작업자가 오류를 던지기 시작할 수 있습니다.

이제 저는 그것이 당신이 정확히 원하는 것일 수 있다는 것을 깨달았습니다. 그래서 이것이 단지 팁인 이유입니다.연산자first '있게미간 '것기때clumsy ' 렸에나 '보다 '가 조금 했습니다.take(1)그러나 소스가 방출되지 않을 가능성이 있는 경우 오류 처리에 주의해야 합니다.하지만 전적으로 당신이 무엇을 하고 있는지에 달려있습니다.


기본값(상수)이 있는 경우:

또한고니다합려도 고려해 ..pipe(defaultIfEmpty(42), first())기본값이 있는 경우 이 값을 사용하여 아무것도 되지 않을 때 사용해야 합니다.물론 이것은 오류를 일으키지 않을 것입니다. 왜냐하면first항상 값을 받습니다.

:defaultIfEmpty 있는 , 이 스림이비있경트우며리되, 는되값이방거출만인 않습니다.null.

관찰할 수 있는 항목 세 가지가 있습니다.A,B,그리고.C대리석 다이어그램으로 사이의 차이점을 탐구합니다.first,take,그리고.single연산자:

첫 번째 대 테이크 대 단일 연산자 비교

범례:
--o--
----! 오류
----|

https://thinkrx.io/rxjs/first-vs-take-vs-single/ 에서 그것을 가지고 놀 수 있습니다.

이미 모든 답을 가지고 있기 때문에, 저는 좀 더 시각적인 설명을 덧붙이고 싶었습니다.

누군가에게 도움이 되길 바랍니다.

어디에도 언급되지 않은 정말 중요한 차이점이 하나 있습니다.

take(1)는 1을 방출하고, 완료하며, 구독 취소

첫 번째 메시지는 1을 내보내고 완료하지만 구독을 취소하지 않습니다.

이는 업스트림 관찰 가능한 것이 첫 번째() 이후에도 여전히 뜨겁다는 것을 의미하며, 이는 예상치 못한 동작일 수 있습니다.

UPD: RxJS 5.2.0을 참조합니다.이 문제는 이미 해결되었을 수 있습니다.

에서는 RxJS 5.2.0이 사용되는 것 ..first()오퍼레이터가 버그가 있습니다.

에 ㅠㅠㅠㅠㅠㅠㅠ.take(1)그리고..first()때 에서사는매경다동수있작습니다할르게우우용하▁quite와 함께 동작할 수 .switchMap:

와 함께take(1)하게 될 입니다: 대로동됩니다게작하예상됩다.

var x = Rx.Observable.interval(1000)
   .do( x=> console.log("One"))
   .take(1)
   .switchMap(x => Rx.Observable.interval(1000))
   .do( x=> console.log("Two"))
   .subscribe((x) => {})

// In the console you will see:
// One
// Two
// Two
// Two
// Two
// etc...

하지만 함께.first()잘못된 행동을 하게 될 것입니다.

var x = Rx.Observable.interval(1000)
  .do( x=> console.log("One"))
  .first()
  .switchMap(x => Rx.Observable.interval(1000))
  .do( x=> console.log("Two"))
  .subscribe((x) => {})

// In console you will see:
// One
// One
// Two
// One
// Two
// One
// etc... 

여기 코데펜에 대한 링크가 있습니다.

두 방법 사이에는 매우 중요한 차이가 있습니다. 이 나오기 전에 스트림이 완료되면 첫 번째()에서 오류가 발생합니다.또는 술어를 제공한 경우(i.e. first(value => value === 'foo'))서술어를 통과하는 값이 나오기 전에 스트림이 완료되면 오류가 발생합니다.

반면에 take(1)는 스트림에서 값이 방출되지 않는 경우 행복하게 계속됩니다.다음은 간단한 예입니다.

const subject$ = new Subject();

// logs "no elements in sequence" when the subject completes
subject$.first().subscribe(null, (err) => console.log(err.message));

// never does anything
subject$.take(1).subscribe(console.log);

subject$.complete();

다른 예제, 술어 사용:

const observable$ = of(1, 2, 3);

// logs "no elements in sequence" when the observable completes
observable$
 .first((value) => value > 5)
 .subscribe(null, (err) => console.log(err.message));

// the above can also be written like this, and will never do
// anything because the filter predicate will never return true
observable$
 .filter((value) => value > 5);
 .take(1)
 .subscribe(console.log);

RxJS에 새로 온 사람으로서, 비록 제가 잘못된 추측을 했기 때문에 제 자신의 잘못이었지만, 이 행동은 저에게 매우 혼란스러웠습니다.제가 서류를 확인하려고 했다면, 그 행동이 명확하게 문서화되어 있다는 것을 알 수 있었을 것입니다.

다음과 같은 경우 오류를 발생시킵니다.defaultValue제공되지 않았으며 일치하는 요소를 찾을 수 없습니다.

제가 이것을 자주 마주치는 이유는 관찰 가능한 것들이 수동으로 정리되는 꽤 흔한 Angular 2 패턴 때문입니다.OnDestroy수명 주기 후크:

class MyComponent implements OnInit, OnDestroy {
  private stream$: Subject = someDelayedStream();
  private destroy$ = new Subject();

  ngOnInit() {
    this.stream$
      .takeUntil(this.destroy$)
      .first()
      .subscribe(doSomething);
  }

  ngOnDestroy() {
    this.destroy$.next(true);
  }
}

코드는 처음에는 해롭지 않아 보이지만 이전에 구성 요소가 파괴되었을 때 문제가 발생합니다.stream$값을 방출할 수 있습니다.사용하고 있기 때문에first()구성 요소가 파괴될 때 오류가 발생합니다.일반적으로 구성 요소 내에서 사용할 값을 얻기 위해 스트림만 구독하기 때문에 스트림이 방출되기 전에 구성 요소가 파괴되어도 상관 없습니다.이것 때문에, 저는 사용하기 시작했습니다.take(1) 곳에서.first().

filter(fn).take(1)보다 조금 더 장황합니다.first(fn)그러나 대부분의 경우 애플리케이션에 궁극적으로 영향을 미치지 않는 오류를 처리하는 것보다 조금 더 자세한 내용을 선호합니다.

또한 주의해야 할 사항은 다음과 같습니다.동일한 내용이 적용됩니다.last()그리고.takeLast(1).

언급

언급URL : https://stackoverflow.com/questions/42345969/take1-vs-first

반응형