Convertir promesa en observable

Resuelto Krishnan Sriram asked hace 54 años • 9 respuestas

Estoy tratando de entender los observables. Me encanta la forma en que los observables resuelven problemas de desarrollo y legibilidad. Según leo, los beneficios son inmensos.

Los observables en HTTP y las colecciones parecen ser sencillos. ¿Cómo puedo convertir algo como esto en un patrón observable?

Esto es de mi componente de servicio, para proporcionar autenticación. Preferiría que esto funcione como otros servicios HTTP en Angular2, con soporte para controladores de datos, errores y finalización.

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

Cualquier ayuda aquí sería muy apreciada. La única solución alternativa que tenía era crear EventEmitters. Pero supongo que es una forma terrible de hacer las cosas en la sección de servicios.

Krishnan Sriram avatar Jan 01 '70 08:01 Krishnan Sriram
Aceptado

Si está utilizando RxJS 6.0.0:

import { from } from 'rxjs';
const observable = from(promise);
Guillaume avatar Jun 11 '2018 13:06 Guillaume

1 Ejecución directa / Conversión

Úselo frompara convertir directamente una Promesa creada previamente en un Observable.

import { from } from 'rxjs';

// getPromise() is called once, the promise is passed to the Observable
const observable$ = from(getPromise());

observable$será un Observable candente que reproducirá efectivamente el valor de las Promesas para los Suscriptores.

Es un Observable de moda porque el productor (en este caso, la Promesa) se crea fuera del Observable. Varios suscriptores compartirán la misma Promesa. Si la Promesa interna se ha resuelto, un nuevo suscriptor del Observable obtendrá su valor inmediatamente.

2 Ejecución diferida en cada suscripción

Úselo defercon una función de fábrica de promesas como entrada para diferir la creación y conversión de una promesa a un observable.

import { defer } from 'rxjs';

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

observable$Será un Observable frío .

Es un Observable frío porque el productor (la Promesa) se crea dentro del Observable. Cada suscriptor creará una nueva Promesa llamando a la función de fábrica de Promesa dada.

Esto le permite crear una Promesa observable$sin crear y, por lo tanto, ejecutar una Promesa de inmediato y sin compartir esta Promesa con múltiples suscriptores. Cada suscriptor observable$llama efectivamente from(promiseFactory()).subscribe(subscriber). Entonces, cada suscriptor crea y convierte su propia Promesa nueva en un nuevo Observable y se adjunta a este nuevo Observable.

3 Muchos operadores aceptan promesas directamente

La mayoría de los operadores RxJS que combinan (p. ej. merge, concat, forkJoin, combineLatest...) o transforman observables (p. ej switchMap. mergeMap, concatMap, , catchError...) aceptan promesas directamente. Si está usando uno de ellos de todos modos, no es necesario que lo use frompara envolver una promesa primero (pero para crear un observable en frío es posible que aún tenga que usarlo defer).

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

Consulte la documentación o implementación para ver si el operador que está utilizando acepta ObservableInputo 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>;

La diferencia entre fromy deferen un ejemplo: 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);

deferes probablemente el operador que la mayoría de la gente busca, ya que muchas aplicaciones dependen de Observables para estar fríos y activar una recuperación de datos al suscribirse. fromSin embargo, sigue siendo una opción viable para ciertos casos de uso, por ejemplo, cuando desea crear una Promesa una vez durante algún proceso de inicialización y luego propagar su valor a través de un Observable al que se suscribirá varias veces, pero no desea crear y ejecutar el Promesa de nuevo para cada suscriptor.

frido avatar Jan 09 '2019 13:01 frido

prueba esto:

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

Puede encontrar una referencia completa al operador fromPromise aquí .

Godfather avatar Sep 04 '2016 16:09 Godfather