Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RxJs Create Observable from resulting Promise

Im fairly new to RxJs and I would like to understand what the best way is to work with Rx in combination with Promises.

What I want to create is a service in Angular that acts much as an event dispatcher pattern and emits an event once a promise is complete. What I also require is that, if there are no (event) subscribers the observable never gets called. The last thing I want to happen is that any subsequent subscribers to the observable get the same result without triggering another request to the server. I have managed to implement my own solution here:

// ... CountryService code

var COUNTRIES_LOADED = Rx.Observable
    .create(function (observer) {
        $http
            .get('/countries')
            .then(function (res) {
                observer.onNext(res);
            }, function (err) {
                observer.onError(err);
            })
            .finally(function () {
                observer.onCompleted();
            });
    })
    .shareReplay();

Now anytime I subscribe a new "listener" to subject the observable will be pulled. Any new subscribers will get the value cached without touching the server again.

So inside my "consumer" (Angular Directive) I would like to do something like this:

// ... countryInput directive code:

COUNTRIES_LOADED.subscribe(function (response) {
    // Fill in countries into scope or ctrl
    scope.countries = response.countries;
});

Any future subscribers to the COUNTRIES_LOADED observer MUST NOT trigger an $http request. Likewise, if the directive is never included on the page, $http will never get called.

The solution above works, however I am not aware of the potential drawbacks and memory implications of this approach. Is this a valid solution? Is there a better / more appropriate way to achieve this using RxJs?

Many thanks!

like image 599
Max101 Avatar asked Aug 05 '16 08:08

Max101


People also ask

Can Promise be converted to Observable?

The correct pattern to transform a promise into an observable is using defer and from operators: import { defer, from } from 'rxjs'; const observable$ = defer(() => from(myPromise())); Why we need the defer operator? Promises are eager, this means that when called they fire instantly.

How do you use Observable instead of Promise?

The biggest difference is that Promises won't change their value once they have been fulfilled. They can only emit (reject, resolve) a single value. On the other hand, observables can emit multiple results. The subscriber will be receiving results until the observer is completed or unsubscribed from.

Is Observable better than Promise?

Often Observable is preferred over Promise because it provides the features of Promise and more. With Observable it doesn't matter if you want to handle 0, 1, or multiple events. You can utilize the same API in each case. Observable also has the advantage over Promise to be cancellable.


2 Answers

Use Rx.Observable.fromPromise(promise)

fromPromise:

Converts a Promises/A+ spec compliant Promise and/or ES2015 compliant Promise or a factory function which returns said Promise to an Observable sequence.

example:

var source = Rx.Observable.fromPromise(promise);

var subscription = source.subscribe(
  function (x) {
    console.log('Next: %s', x);
  },
  function (err) {
    console.log('Error: %s', err);
  },
  function () {
    console.log('Completed');
  });

update

rxjs6 method is from

like image 167
cmd Avatar answered Sep 18 '22 14:09

cmd


update

As of rxjs6 you can use from()


Did you tried to use the fromPromise() API of rxjs5 ?

Check it's documentation here !

like image 24
Clement Avatar answered Sep 17 '22 14:09

Clement