Convert Promise to Observable

自闭症网瘾萝莉.ら 提交于 2019-12-17 02:09:25

问题


I am trying to wrap my head around observables. I love the way observables solve development and readability issues. As I read, benefits are immense.

Observables on HTTP and collections seem to be straight forward. How can I convert something like this to observable pattern.

This is from my service component, to provide authentication. I'd prefer this to work like other HTTP services in Angular2 - with support for data, error and completion handlers.

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;
    // ...
  });

Any help here would be much appreciated. The only alternative solution I had was to create EventEmitters. But I guess that's a terrible way to do things in services section


回答1:


If you are using RxJS 6.0.0:

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



回答2:


try this:

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

you can find complete reference to fromPromise operator here.




回答3:


Direct, single execution

Use from to directly convert a previously created Promise to an Observable.

import { from } from 'rxjs';

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

The Promise's body is being executed or has already been resolved when the Observable is created. If the inner Promise has already been resolved a new Subscriber to the Observable will get its value immediately (getPromise() won't be called again).

Many functions and operators accepts Promises directly

Most RxJS functions that create Observables (e.g. merge, concat, forkJoin, combineLatest ...) and many operators (e.g. switchMap, mergeMap, concatMap, catchError ...) accept Promises directly. If you're using one of them anyway you don't have to use from to wrap a Promise first.

// You can do this for example
forkJoin(getPromise(1), getPromise(2)).pipe(
  switchMap(values => getPromise(values))
)

Check the documentation or implementation to see if the function you're using is supporting ObservableInput or SubscribableOrPromise.

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

Deferred execution on every subscribe

Use defer with a Promise factory function as input to defer the creation and conversion of a Promise to an Observable.

import { defer } from 'rxjs';

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

The difference to from is that defer waits for a subscriber and only then creates a new Promise by calling the given Promise factory function. This is useful when you want to create an Observable but don't want the inner Promise to be executed right away. The inner Promise will only be executed when someone subscribes to the Observable. Each subscriber will also get its own new Observable.

The difference between from and defer in an example: 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:


You can also use a Subject and trigger its next() function from promise. See sample below:

Add code like below ( I used service )

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);
          // ...
        });
    }

  }
}

Create User From Component like below

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


来源:https://stackoverflow.com/questions/39319279/convert-promise-to-observable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!