일회성 구독 만들기


182

구독 Observable이 처음 호출 될 때 즉시 처리 되는 구독을 만들어야합니다 .

다음과 같은 것이 있습니까?

observable.subscribeOnce(func);

사용 사례, 빠른 경로 처리기에서 구독을 만들고 구독이 요청 당 여러 번 호출됩니다.

답변:


319

당신이 필요로하는 일에 대해 확실하지 100 % 당신이 첫 번째 값을 관찰하려면,하지만, 다음 중 하나를 사용 first()하거나 take(1):

observable.first().subscribe(func);

참고 : .take(1).first()모두 탈퇴가 자동으로 조건이 충족 될 때

RxJS 5.5 이상에서 업데이트

Coderer의 코멘트에서 .

import { first } from 'rxjs/operators'

observable
  .pipe(first())
  .subscribe(func);

이유는 다음과 같습니다


33
구독 후 자동으로 정리됩니까?
버클리 마르티네즈

50
그렇습니다. 조건이 충족되면 먼저 구독을 취소하십시오.
Brandon

20
문서에서 구독을 자동으로 처리한다고 말하지 않는 이유는 무엇입니까?
jzig

17
관찰 가능한 스트림이 종료되면 구독이 삭제되는 것이 일반적인 RxJS 규칙입니다. 즉, 스트림을 "단축"하거나 다른 유형의 스트림으로 변환하는 연산자는 작업이 완료되면 소스 스트림에서 구독을 취소합니다. 이것이 문서의 어디에 또는 있는지 확실하지 않습니다.
Brandon

37
사람이 2018이 오는 경우, 당신은 실제로 원하는 observable.pipe(first()).subscribe(func)first에서 온다 rxjs/operators.
Coderer

32

RxJS에는 내가 본 최고의 문서 중 일부가 있습니다. 벨로우즈 링크를 따라 가면 사용자에게 매우 유용한 테이블 매핑 사용 사례로 이동합니다. 예를 들어, 아래의 유스 케이스 "나는 첫 번째 값을 원하는 것은"세 사업자는 다음과 같습니다 first, firstOrDefault그리고 sample.

관찰 가능한 시퀀스가 ​​통지없이 완료되면 운영자는 first가입자에게 오류를 알리는 반면 firstOrDefault운영자는 가입자에게 기본값을 제공합니다.

운영자 유스 케이스 조회


3

Observable을 한 번만 호출하려면 스트림을 기다리지 않을 것입니다. 따라서 구독 취소가 필요하지 않으므로 toPromise()대신 대신 사용 subscribe()하면 충분합니다 toPromise().


매우 흥미로운,이 또한 의미 우리가 할 수있는 단지 그것을 하나 라이너 만드는awaitpromise
루이 Almeda

@LouieAlmeda 하나의 라이너 예제를 제공해 주시겠습니까?
Ado Ren

안녕하세요 @ AdoRen, 나는 당신을 위해 여기에 대한 답변으로 기술을 설명했습니다, 그것이 도움이되기를 바랍니다.
Louie Almeda

2

보충 브랜든의 대답 @ , 사용 first()또는 같은이 업데이트를 위해 필수적입니다 BehaviorSubject그 기반으로 Observable. 예를 들어 (평가되지 않음) :

var subject = new BehaviorSubject({1:'apple',2:'banana'});
var observable = subject.asObservable();

observable
  .pipe(
    first(), // <-- Ensures no stack overflow
    flatMap(function(obj) {
      obj[3] = 'pear';
      return of(obj);
    })
  )
  .subscribe(function(obj) {
    subject.next(obj);
  });

2

깨끗하고 편리한 버전

M Fuat NUROĞLU에서 Observable을 약속으로 변환하는 것에 대한 놀라운 답변을 확장하면 여기에 매우 편리한 버전이 있습니다.

const value = await observable.toPromise();

console.log(value)

이것의 장점은 다른 중첩 블록을 도입하지 않고도 해당 값을 일반 변수처럼 사용할 수 있다는 것입니다!

이는 여러 관측 가능 항목에서 여러 값을 가져와야 할 때 특히 유용합니다. 청초한.

const content = await contentObservable.toPromise();
const isAuthenticated = await isAuthenticatedObservable.toPromise();

if(isAuthenticated){
   service.foo(content)
}

물론이 경로를 사용하려면 포함 기능을 만들어야 async합니다. .then포함 함수가 비동기 적이기를 원하지 않는 경우 에도 약속을 할 수 있습니다

이 접근 방식과의 타협이 있는지 확실하지 않으면 의견에 언제든지 알려주십시오.

PS이 답변이 마음에 드 셨다면, M Fuat NUROĞLU의 답변을 공감하는 것을 잊지 마십시오 :)


0

나는 비슷한 질문을했다.

아래는 다른 상태 체인저에서 나중에 호출되었습니다. 내가 원하지 않았던 것처럼.

function foo() {
    // this was called many times which was not needed
    observable.subscribe(func);
    changeObservableState("new value");
}

unsubscribe()아래와 같이 구독 후 시도하기로 결정했습니다 .

function foo() {
    // this was called ONE TIME
    observable.subscribe(func).unsubscribe();
    changeObservableState("new value");
}

subscribe(func).unsubscribe();같다 subscribeOnce(func).

도움이 되었기를 바랍니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.