약속을 관찰 가능으로 변환


214

나는 관찰 가능한 물건으로 머리를 감싸려고합니다. 나는 관측 가능 항목이 개발 및 가독성 문제를 해결하는 방식을 좋아합니다. 내가 읽을 때, 혜택은 엄청납니다.

HTTP 및 컬렉션의 관찰 가능 항목은 간단합니다. 이와 같은 것을 관찰 가능한 패턴으로 변환하는 방법은 무엇입니까?

이것은 인증을 제공하기 위해 서비스 컴포넌트에서 가져온 것입니다. 데이터, 오류 및 완료 처리기를 지원하는 Angular2의 다른 HTTP 서비스처럼 작동하기를 원합니다.

firebase.auth().createUserWithEmailAndPassword(email, password)
  .then(function(firebaseUser) {
    // do something to update your UI component
    // pass user object to UI component
  })
  .catch(function(error) {
    // Handle Errors here.
    var errorCode = error.code;
    var errorMessage = error.message;
    // ...
  });

여기에 도움이 될 것입니다. 내가 가진 유일한 대안은을 만드는 것이 었습니다 EventEmitter. 그러나 나는 그것이 서비스 섹션에서 일을하는 끔찍한 방법이라고 생각합니다

답변:


319

RxJS 6.0.0을 사용중인 경우 :

import { from } from 'rxjs';
const observable = from(promise);

9
6.3.3을 사용하여 from메소드는 관찰 가능을 반환하지만 구독에 가치로 약속을 보내고 있습니다. :(
Laxmikant Dange

1
이 답변은 RXJS 6+에 적합합니다. operators"직관" 을 통해 가져 오려고했습니다 . 잘못되었습니다.
VSO

119

이 시도:

import 'rxjs/add/observable/fromPromise';
import { Observable } from "rxjs/Observable";

const subscription = Observable.fromPromise(
    firebase.auth().createUserWithEmailAndPassword(email, password)
);
subscription.subscribe(firebaseUser => /* Do anything with data received */,
                       error => /* Handle error here */);

fromPromise 연산자에 대한 완전한 참조는 여기를 참조 하십시오 .


47
import 'rxjs/add/observable/fromPromise';
Simon Briggs

16
import { Observable } from "rxjs/Observable"; :)
Luckylooke

41

1 직접 실행 / 변환

from이전에 생성 된 약속을 관찰 가능 항목으로 직접 변환하는 데 사용 합니다.

import { from } from 'rxjs';

// getPromise() will only be called once
const observable$ = from(getPromise());

observable$구독자에게 약속 가치를 효과적으로 재생 하는 뜨거운 관측 가능 합니다.

Observable이 작성 될 때 약속 본문이 실행 중이거나 이미 해결되었습니다. 내부 약속이 해결 된 경우 옵저버 블에 대한 신규 가입자는 즉시 가치를 얻습니다.

모든 구독에 대해 2 개의 지연된 실행

defer약속의 팩토리 기능을 입력으로 사용 하여 약속의 생성 및 관찰을 관찰 가능으로 지연시킵니다.

import { defer } from 'rxjs';

// getPromise() will be called every time someone subscribes to the observable$
const observable$ = defer(() => getPromise());

observable$차가운 관측 가능할 것입니다 .

차이점 fromdefer가입자 를 기다렸다가 주어진 약속 팩토리 함수를 호출하여 새 약속을 작성한다는 것입니다. 이것은 Observable을 만들고 싶지만 내면의 약속을 즉시 실행하고 싶지 않을 때 유용합니다. 내면의 약속은 누군가가 옵저버 블에 가입 한 경우에만 실행됩니다. 각 가입자는 또한 자신의 새로운 관찰 대상을 얻게됩니다.

3 많은 운영자가 직접 약속을 받아들입니다

결합 대부분의 RxJS 사업자 (예를 들어 merge, concat, forkJoin, combineLatest...) 또는 (예를 들어, 관찰 가능한 변환 switchMap, mergeMap, concatMap, catchError...) 직접 약속을 받아들입니다. 어쨌든 그중 하나를 사용 from하는 경우 약속을 먼저 ​​포장하는 데 사용할 필요는 없습니다 (그러나 차가운 관찰 가능 을 만들려면 여전히을 사용해야 할 수도 있습니다 defer).

// Execute two promises simultaneously
forkJoin(getPromise(1), getPromise(2)).pipe(
  switchMap(([v1, v2]) => v1.getPromise(v2)) // map to nested Promise
)

사용중인 연산자가 또는 을 수락하는지 확인하려면 설명서 또는 구현 을 확인하십시오 .ObservableInputSubscribableOrPromise

type ObservableInput<T> = SubscribableOrPromise<T> | ArrayLike<T> | Iterable<T>;
// Note the PromiseLike ----------------------------------------------------v
type SubscribableOrPromise<T> = Subscribable<T> | Subscribable<never> | PromiseLike<T> | InteropObservable<T>;

fromdefer https://stackblitz.com/edit/rxjs-6rb7vf 의 차이점

const getPromise = val => new Promise(resolve => {
  console.log('Promise created for', val);
  setTimeout(() => resolve(`Promise Resolved: ${val}`), 5000);
});

// the execution of getPromise('FROM') starts here, when you create the promise inside from
const fromPromise$ = from(getPromise('FROM'));
const deferPromise$ = defer(() => getPromise('DEFER'));

fromPromise$.subscribe(console.log);
// the execution of getPromise('DEFER') starts here, when you subscribe to deferPromise$
deferPromise$.subscribe(console.log);

4
차이가 자본이라고 생각합니다. 지적 해 주셔서 감사합니다.
Starscream

1

Subject를 사용하여 promise에서 next () 함수를 트리거 할 수도 있습니다 . 아래 샘플을 참조하십시오.

아래와 같은 코드를 추가하십시오 (서비스를 사용했습니다)

class UserService {
  private createUserSubject: Subject < any > ;

  createUserWithEmailAndPassword() {
    if (this.createUserSubject) {
      return this.createUserSubject;
    } else {
      this.createUserSubject = new Subject < any > ();
      firebase.auth().createUserWithEmailAndPassword(email,
          password)
        .then(function(firebaseUser) {
          // do something to update your UI component
          // pass user object to UI component
          this.createUserSubject.next(firebaseUser);
        })
        .catch(function(error) {
          // Handle Errors here.
          var errorCode = error.code;
          var errorMessage = error.message;
          this.createUserSubject.error(error);
          // ...
        });
    }

  }
}

아래와 같이 컴포넌트에서 사용자 생성

class UserComponent {
  constructor(private userService: UserService) {
    this.userService.createUserWithEmailAndPassword().subscribe(user => console.log(user), error => console.log(error);
    }
  }


과목은 저급 기계입니다. 확장중인 경우를 제외하고는 주제를 사용하지 마십시오 rxjs.
polkovnikov.ph 2014

방금 해결책을 제시하고 있습니다.
Shivang Gupta

적어도 new Observable(observer => { ... observer.next() ... })그것을 구현하는 방법을 보여 주었을 것입니다. 기존의 잘 알려진 기능을 다시 구현하더라도 질문에 직접 대답하고 독자에게는 해롭지 않습니다.
polkovnikov.ph 2014

1

defer 를 사용할 수도 있습니다 . 가장 큰 차이점은 약속이 간절히 해결하거나 거부 하지 않는다는 것입니다.


0

promise 기능 주위에 래퍼를 추가하여 Observable을 옵저버에게 반환 할 수 있습니다.

  • 만들기 게으른 사용하여 관찰 가능한을 연기 () 만 때 옵저버 구독 관찰을 만들 수 있습니다 연산자를.
import { of, Observable, defer } from 'rxjs'; 
import { map } from 'rxjs/operators';


function getTodos$(): Observable<any> {
  return defer(()=>{
    return fetch('https://jsonplaceholder.typicode.com/todos/1')
      .then(response => response.json())
      .then(json => {
        return json;
      })
  });
}

getTodos$().
 subscribe(
   (next)=>{
     console.log('Data is:', next);
   }
)

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