programing

take (1) 대 first ()

nasanasas 2020. 9. 24. 07:54
반응형

take (1) 대 first ()


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));

그런 다음 소스 Observable이 비어 있으면 오류가 발생하지 않습니다.

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

2019 년 1 월 : RxJS 6 업데이트


팁 : 다음 first()경우 에만 사용 하십시오.

  • 당신은 제로 항목 (발광하기 전에 완료 예.) 오류 상태로 방출 고려오류의 큰 0 % 이상 기회가 있다면 당신은 정상적으로 그것을 처리
  • 또는 관찰 가능한 소스가 1 개 이상의 항목을 방출한다는 것을 100 % 알고 있습니다 (따라서 절대 던질 수 없음) .

배출이 제로이고 명시 적으로 처리하지 않으면 (을 사용하여 catchError) 해당 오류가 전파되어 다른 곳에서 예상치 못한 문제를 일으킬 수 있으며 추적하기가 매우 까다로울 수 있습니다.

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

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

참고 : 다음 같이 술어를 사용할 있습니다 .. 10보다 크지 않으면 오류가 없습니다.take(1).pipe( filter(x => x > 10), take(1) )

이건 어떤가요 single()

더 엄격하고 두 개의 방출을 허용하지 않으려면 방출 single()0 또는 2+ 인 경우 어떤 오류를 사용할 수 있습니다 . 이 경우에도 오류를 처리해야합니다.

팁 : Single옵저버 블 체인이 http 서비스를 두 번 호출하고 두 개의 옵저버 블을 내보내는 것과 같은 추가 작업을 수행하지 않도록하려는 경우 유용 할 수 있습니다. single파이프 끝에 추가하면 그러한 실수를했는지 알 수 있습니다. 저는 하나의 값만 방출해야하는 Observable 작업을 전달하는 '작업 실행자'에서 사용하고 있으므로 single(), catchError()좋은 동작을 보장하기 위해 응답을 전달합니다 .


왜 항상 first()대신 사용 하지 take(1)않습니까?

일명. first 잠재적 으로 더 많은 오류를 일으킬 있는 방법

서비스에서 무언가를 가져 와서 파이프하는 Observable이 있다면 first()대부분의 경우 괜찮을 것입니다. 사람이 어떤 이유에 대한 서비스를 사용하지 않도록 함께 제공한다면 - 및 변경이 방출하는 of(null)또는 NEVER다음 다운 스트림 first()연산자는 오류를 던지기 시작합니다.

이제 나는 그것이 정확히 당신이 원하는 것일 수 있음을 깨달았습니다. 그러므로 이것이 단지 팁인 이유입니다. 운영자 first는 그것이 '서투른'소리가 약간 덜 들렸 기 때문에 나에게 호소 take(1)했지만 소스가 방출되지 않을 가능성이 있다면 오류 처리에 조심해야합니다. 하지만 당신이하는 일에 전적으로 의존 할 것입니다.


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

.pipe(defaultIfEmpty(42), first())아무것도 내 보내지 않는 경우 사용해야하는 기본값이 있는지도 고려하십시오 . 물론 first항상 값을 받기 때문에 오류가 발생하지 않습니다 .

defaultIfEmpty에만 스트림이 비어있는 경우 트리거가 방출되는 것의 값이없는 경우 null.


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

take (1) 방출 1, 완료, 구독 취소

first ()는 1을 내보내고 완료되지만 구독을 취소하지는 않습니다.

이는 예상되는 동작이 아닌 first () 이후에도 업스트림 관찰 가능 항목이 여전히 뜨겁다는 것을 의미합니다.

UPD : RxJS 5.2.0을 의미합니다. 이 문제는 이미 수정되었을 수 있습니다.


RxJS 5.2.0에서 .first()운영자에게 버그 가있는 것 같습니다 .

그 때문에 버그 .take(1).first()당신이 그들을 사용하는 경우 매우 다른 행동을 할 수 있습니다 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... 

다음은 codepen에 대한 링크입니다.


여기에 세 가지 Observables은있다 A, B그리고 C대리석 다이어그램의 차이를 탐구 first, take그리고 single운영자는 :

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

* 범례 :
--o--
----! 오류
----| 완료

https://thinkrx.io/rxjs/first-vs-take-vs-single/ 에서 플레이 하세요 .

이미 모든 답을 알고있어 더 시각적 인 설명을 추가하고 싶었습니다.

누군가에게 도움이되기를 바랍니다

참고 URL : https://stackoverflow.com/questions/42345969/take1-vs-first

반응형