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!
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.
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.
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.
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
update
As of rxjs6 you can use from()
Did you tried to use the fromPromise()
API of rxjs5 ?
Check it's documentation here !
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With