I'm still figuring out reactive programming so I'm pretty sure this is very basic, but the number of stream transformations is pretty overwhelming to a beginner.
I'm creating an Observable from a DOM event. This event should in turn trigger a REST call and all other DOM events will be ignored until this event has been resolved.
const stream = Observable.fromEvent(document, 'some-event')
stream
.flatMap(() => httpRestService())
.subscribe(() => {
})
How do I ignore the events from the stream until the last HTTP promise has resolved?
DOM event
A - - - - B - - - - C
HTTP event
D ...........done - C
You could try flatMapFirst which seems to do what you want. The following code could work (jsfiddle here - click anywhere) :
const stream = Observable.fromEvent(document, 'some-event')
stream
.flatMapFirst(() => httpRestService())
.subscribe(() => {
})
Quoting the documentation :
The flatMapFirst operator is similar to the flatMap and concatMap methods described above, however, rather than emitting all of the items emitted by all of the Observables that the operator generates by transforming items from the source Observable, flatMapFirst instead propagates the first Observable exclusively until it completes before it begins subscribes to the next Observable. Observables that come before the current Observable completes will be dropped and will not propagate.
UPDATE
Looking at the source code (https://github.com/Reactive-Extensions/RxJS/blob/master/src/core/linq/observable/switchfirst.js) it seems that while the the current observable has not completed, all the incoming observables in the meantime will be discarded, i.e. not subscribed to.
So if subscribing to these observables triggers the http call (would be interesting to see the code for httpRestService), then there is no unnecessary http call. If those calls are triggered immediately by calling the function and the result is passed through an observable, then there is a possibility that those calls are indeed triggered unnecessarily. In which case, that issue is easily solvable with using the defer operator to do the http call only at subscription time. In short, you need lazy execution of the rest request if you don't already have it.
Related
I recently dived into subscriptions of Subject/BehaviorSubject/ etc and I am looking for the goto approach when used in combinations with Promises.
Given is the example code below:
firebase.user.subscribe((user: any | null) => {
fs.readFile('path/to/file')
.then((buf: Buffer) => {
this.modifySomeData = buf;
});
});
I subscribe to a Subject that triggers whenever the user logs in or out of their service. Whenever this happens, I read a file from disk. This readFile event could potentially take longer than the next "login/logout" event. Of course, I am in JS and in an asynchronous environment. This means, my user code is not multithreaded, but still, the 2nd user event and 2nd readFile could theoretically be faster than the first readFile.
First user event fired
First readFile is executed
Second user event is fired
Second readFile is executed
Second readFile is resolved <---
First readFile is resolved <---
The order is mixed up. The silliest approach I could think of is to create a uuid before reading the file and check inside the promise if this is still the same. If it's not I discard the data.
Is there a better solution?
If i have a process where older requests can be discarded i often keep a variable in scope to track the latest request and compare, similar to your UUID idea:
let lastRead: Promise<Buffer> | null = null;
firebase.user.subscribe((user: any | null) => {
const read = lastRead = fs.readFile('path/to/file');
read.then((buf: Buffer) => {
if (read != lastRead)
return;
this.modifySomeData = buf;
});
});
In this specific case, readFile also supports an abort signal. So you might also be able to abort the last request instead; you will still need to track it though.
The first approach is to see if your event generation logic could handle waiting for event handling. For example, you can use a promise to wait for the event OR generate another event, say doneReadFile and only then send the next event. Usually, this is not the case for a generic (distributed) environment.
If event generation does not care about how long it took to handle events, you can still use the above approach but check for the intermediate event doneReadFile in the next event handler (login/logout). This can be achieved by implementing some kind of polling or busy-wait/sleep
I have problems understand the execution model/order of RxJS Observables and Subjects.
I read a lot of literature and blog posts about RxJS observables being the better promise since their subscription can be canceled and they can emit multiple results/values via next().
This question might be answered easily but how does RxJS create or simulate asynchronism?
Does RxJS Observables wrap around promises and create a sequence of promises to make the code execution asynchronous? Or is it because of the implemented observable pattern that change is propagated asynchronous to subscribers but code execution is still synchronous?
In my point of view javascript code is asynchronous when it is handle via callbacks in any of the JavaScript callback queues processed by the event loop.
In RxJS, everything is about producer. The producer can be anything and it can be synchronous or asynchronous, thus Observables can both emit synchronously or asynchronously.
Lets try to understand what is (a)synchronous behavior. I will leave couple of links for deeper understanding of the subject: a talk by Philip Roberts, another talk by Jake Archibald and Jake's blog if you don't like watching long videos.
Tl;dw(atch): all JavaScript code is synchronous and executes within a single thread. On the other hand, WebAPIs, which can be accessed from JS code, may execute some other stuff in other threads and bring back the result to the JavaScript runtime. And the results are passed through to the runtime by Event loop and the callbacks. So, when you say:
In my point of view javascript code is asynchronous when it is handle via callbacks in any of the JavaScript callback queues processed by the event loop.
You're right. A callback handled by the Event loop is the asynchronous callback. Examples of WebAPIs which have asynchronous callbacks are: setTimeout and setInterval, DOM events, XHR events, Fetch events, Web workers, Web sockets, Promises, MutationObserver callbacks and so on. The last two (Promises and MutationObservers) schedule tasks on a different queue (microtask queue), but it's still asynchronous.
Back to RxJS. I already told that in RxJS it's everything about the producer. Observables wrap producers using observers. To quote Ben Lesh from the article:
[A producer] is anything you’re using to get values and pass them to observer.next(value).
This means that the code that is synchronous (and all JS code is) will synchronously emit values when wrapped with an Observable. For example:
import { Observable } from 'rxjs';
const o = new Observable(observer => {
[1, 2, 3].forEach(i => observer.next(i));
observer.complete();
});
o.subscribe(x => console.log(x));
console.log('Anything logged after this?');
Logs:
1
2
3
Anything logged after this?
On the other hand, next example uses setTimeout (which is not part of the ECMAScript specification and uses asynchronous callback):
import { Observable } from 'rxjs';
const o = new Observable(observer => {
setTimeout(() => {
observer.next(1);
observer.complete();
}, 0);
});
o.subscribe(x => console.log(x));
console.log('Anything logged after this?');
Logs this:
Anything logged after this?
1
This means that, even though I subscribed to the source observable before last console.log, we've got the message before observer sent next value. This is because of the asynchronous nature of setTimeout.
In fact, RxJS has many ways of creating Observables so that you don't have to write your own implementations by wrapping all of this.
So, improved first example:
import { from } from 'rxjs';
from([1, 2, 3]).subscribe(i => console.log(i));
console.log('Anything logged after this?');
Or improved second example:
import { of, scheduled, asyncScheduler } from 'rxjs';
scheduled(of(1), asyncScheduler).subscribe(i => console.log(i));
console.log('Anything logged after this?');
scheduled creation operator uses schedulers for dispatching events on different task queues. asyncScheduler internally uses setTimeout to dispatch the event to the macrotask queue, while asapScheduler internally uses Promises as it uses microtask queue.
However, setTimeout is the most obvious and the most repeated example of asynchronous behavior. XHR is the one that is much more interesting to us. Angular's HTTP client does the same wrapping as I did in my first two examples, so that, when response comes, it is transferred to the responseObserver using next.
When the response comes from the server, XMLHttpRequest object puts it to macrotask queue which gets pushed to the call stack by Event loop once call stack is cleared, and the message can be passed to the responseObserver.
This way, the asynchronous event happens, and the subscribers to the Observable that wraps that XMLHttpRequest object get their value asynchronously.
I read a lot of literature and blog posts about RxJS observables being the better promise since their subscription can be canceled and they can emit multiple results/values via next().
The difference between Observables and Promises is indeed in the fact that Observables are cancelable. This is the most important when you're working a lot with WebAPIs as many of them need to have means to be cancelable (so that resources are not lost when we stop using them).
In fact, since RxJS has many creation operators that wrap many of the WebAPIs, they're already dealing with the cancelation stuff for you. All you have to do is to keep track of the subscriptions and to unsubscribe at the right moment. Article that might be helpful for that can be found here.
Does RxJS Observables wrap around promises and create a sequence of promises to make the code execution asynchronous?
No, they wrap a producer. Anything that can call observer.next method. If a producer uses asynchronous callbacks which call observer.next method, then Observables emit asynchronously. Other way around, they emit synchronously.
But, even though original emissions are synchronous, they can be dispatched to be emitted asynchronously by using schedulers.
Good rule of thumb is that in RxJS everything is synchronous unless you work with time. This default behavior has changed between RxJS 4 and RxJS 5+. So for example range(), from() or of() these all are synchronous. All inner subscriptions inside switchMap, mergeMap, forkJoin, etc. are synchronous. This means that you can easily make infinite loops if you emit from subscribe():
const subject$ = new Subject();
const stop$ = new Subject();
subject$.pipe(
tap(() => /* whatever */)
takeUntil(stop),
).subscribe(() => {
subject$.next();
stop$.next();
});
This example will never reach stop$.next().
A common source of confusion is using combineLatest() with synchronous sources. For example both combineLatest() and range() emit synchronously. Try to guess what series of values this chain emits. We want to get all combinations from the two range Observables:
import { combineLatest, range} from 'rxjs';
combineLatest([
range(1, 5),
range(1, 5),
]).subscribe(console.log);
Live demo: https://stackblitz.com/edit/rxjs-p863rv
This emitted only five values where the first number is always 5 which is weird at the first sight. If we want to emit all combinations we would have to chain each range() with delay(0) or use asyncScheduler or use subscribeOn(asyncScheduler) operator to force async behavior.
combineLatest([
range(1, 5, asyncScheduler),
range(1, 5, asyncScheduler),
]).subscribe(console.log);
Live demo: https://stackblitz.com/edit/rxjs-tnxonz
I believe RxJS does not run on Promises internally. It's just how the whole publish-subscribe pattern works. If simplified basically you have Observer, Observable and Subscriber. If you ever created your own observable, you could see that you can wrap it around basically anything: promises, events, http calls even synchronous code like just reading array. The way it's achieved is that Observer has methods next and complete (but not limited to them, e.g. there is also error). Whenever you call .next() on your Observer all subscribers of Observable will have onNext called. That's because through Observable Observer is connected to Subscribers and whenever you call .next() it will call onNext. Where onNext along with onError and onComplete are just callbacks that you're supplying to subscriber when calling .subscribe(). Which means that if you call .next() after a promise resolves it will be asynchronous.
Here is an example:
new Observable<T>((observer: Observer<T>) => {
Promise.resolve(() => {
observer.next()
observer.complete()
})
})
If you subscribe to this observable it will call your onNext asynchronously.
but you can also do something like:
const array = [1,2,3,4,5]
new Observable<T>((observer: Observer<T>) => {
array.forEach((num) => observer.next(num))
observer.complete()
})
Subscribing to this in theory should be synchronous. But you can play around with it. Thing is that rxjs also has such thing as Scheduler which allows you to control the nature of your Observable, but there are also limitations I believe.
There is also a video of simple pattern implementation that helps understanding how it works.
This article describes the refCount operator and explains that in order to prevent the unsubscription of obervable A we have to add delay(0) to the source observable such that th import { Observable } from "rxjs/Observable";
const source = Observable.defer(() => Observable.of(
Math.floor(Math.random() * 100)
)).delay(0);
Is 0 always enough? In other words does passing zero guarantee that the notification will be delayed until all m.subscribe() statements have run, assuming they are all run immediately following the multicast statement like this:
const m = source.multicast(() => new Subject<number>()).refCount();
m.subscribe(observer("a"));
m.subscribe(observer("b"));
In the above case we are only subscribing observers a and b. If we subscribed a million observers after the multicast statement would running delay(0) still guarantee taht they all will be subscribed before the first source notification happens?
To understand the issue you must know that:
Javascript is single threaded;
Asynchronous events runs in event loop (a.k.a. Micro Task and Macro Task)
When Async event happens, it is added to the Event loop;
After async event added to the Event loop, Javascript continues with synchronous code;
After no synchronous code left, it runs events code from Event loop.
This Observable would be synchronous if you wouldn't add delay(0):
const source = Observable.defer(() => Observable.of(
Math.floor(Math.random() * 100)
)).delay(0);
When first Subscription happens (subscribing is synchronous code), Observable emits immediately, because it is also synchronous. But if you add delay(0) (similar to setTimeout), Javascript will wait until all synchronous code (all source.subscribe() in this case), are executed. After that it will run asynchronous delay(0)).
And here:
const m = source.multicast(() => new Subject<number>()).refCount();
m.subscribe(observer("a"));
m.subscribe(observer("b"));
You have source Observable which becomes asynchronous after its emition is passed to delay(0). At that point, synchronous code will continue (all your other source.subscribe() calls) and after they are done, synchronous delay(0) will emit.
So it is safe even for millions source.subscribe() calls to get executed in this case.
p.s.
multicast(() => new Subject<number>()).refCount() is exactly the same as share() - it takes multicast with Subject factory and counts active subscriptions with refCount.
I have an expensive calculation that is called by an effect. I now want to ensure, that this calculation is never called concurrently, i.e. if it is called a second time while the first call is still running, the second call should be ignored.
My approach to this problem was to create 2 actions: calculate and setLoading.
#Effect()
calculate$ = this.updates$
.whenAction(CALCULATE)
.flatMap(data => {
console.debug('LOADING', data.state.loading);
if (!data.state.loading) {
this.store.dispatch(Actions.setLoading(true));
await DO_THE_EXPENSIVE_CALCULATION();
this.store.dispatch(Actions.setLoading(false));
}
});
with Actions.setLoading obviously setting state.loading. However, if I start the calculation 2 times in a row:
store.dispatch(Actions.calculate());
store.dispatch(Actions.calculate());
the output is
LOADING false
LOADING false
and therefore, the expensive calculation is executed two times.
How can I prevent this?
You might see the LOADING false twice because the Action.setLoading have not been executed yet. This is very possible depending on the synchrony/asynchrony of dispatching and actions. Best is to not make hypothesis about that.
Generally speaking, if you want to limit a number of operations executing at the same time/execute only one operation at a time, there are a number of operators you could use in rxjs v4/v5:
flatMapWithMaxConcurrent|mergeMap : will subscribe to the parameterized maximum of observables concurrently, keep a buffer of the remaining observables to subscribe to, and subscribe to them when a slot becomes available. Hence there is no loss.
flatMapFirst|exhaustMap : will only subscribe to one observable at a given time. Observable which come while the current observable is being executed are lost. When the current observable is completed, new observables can be subscribed to.
concatMap : will subscribe only to one observable at a time. Will keep a buffer of remaining observables to subscribe to, and will do that in order when the current observable has completed. Hence there is no loss.
You can also review the following question : Batching using RxJS?
In conclusion, maybe something like this could work for you :
#Effect()
calculate$ = this.updates$
.whenAction(CALCULATE)
.exhaustMap(data => DO_THE_EXPENSIVE_CALCULATION())
;
I supposed here that the DO_THE_EXPENSIVE_CALCULATION() returns a promise (could also be an observable).
So i've read that observables are looking to overtake promises in terms of usage in some of upcoming JavaScript MVC's:
Angular 2.0
Falcor used by Netflix
What is the difference between observables and promises?
Updated: Apologies! removed my falsy statement.
What is the difference between observables and promises?
Simply put: A promise resolves to a single value asynchronously, an observable resolves to (or emits) multiple values asynchronously (over time).
Concrete examples:
Promise: Response from an Ajax call
Observable: Click events
More information can be found here: http://reactivex.io/intro.html
i've read that observables are looking to overtake promises
Unlikely. Observables might be the better solution to certain problems, but that doesn't make promises obsolete (if that's what you mean).
Promises are a representation of 1 future value.
Observables are a representation for a possibly infinite amount of values.
Promises will trigger the fetching of that value immediately upon creation.
Observables will only start producing values when you subscribe to them. (Unless it's a hot observable, but that's outside the scope of this question)
Promises are designed to represent AJAX calls.
Observables are designed to represent anything: events, data from databases, data from ajax calls, (possibly infinite) sequences, etc.
Promises offer a very simplistic call back mechanism, where as Rx offers a powerful abstraction over asynchronous programming. An Observable represents a stream of data, which we can then apply operators to in order to define how the incoming data should be treated.
If all you need to do is make an HTTP request and then update a UI component, then using a Promise might suffice.
However, most apps tend to have more complicated needs than that (even if it’s not obvious at the first). Taking our HTTP request for example, let’s see how modelling this as an Observable and using some of the Rx operators can help us:
-If the HTTP request is triggered by a user action, we might want to be wary of firing off multiple HTTP requests (imagine a user typing into a search box). We don’t want to fire a request for every keystroke, so we might want to Throttle our search, so that we only fire a request if the user stops typing for 300ms. Furthermore, if user types a word, waits 300ms, and adds another character, we’ll fire off a subsequent HTTP request. With Promises, we’d probably encounter a race condition as we can’t control the order in which we’ll receive the responses and we can’t cancel old requests. Rx solves this by allowing us to Switch between streams, which calls Dispose on the old request subscriptions we no longer care about. We might also filter out any invalid search inputs, for instance Where the search term is less than 3 characters in length.
-Support for dealing with Timeouts/Error handling. Let’s say our HTTP request fails, Rx allows us to easily Retry making the request.
-Let’s say several parts of our application need to make the same HTTP call, we probably don’t want to actually make the call more than once. We can expose our observable to multiple consumers and use Replay to ensure the call is made once and the result is cached for subsequent subscribers. We can even supply a TimeSpan to Replay, giving us expiring cache behaviour.
-Powerful abstraction over threading through the use of Schedulers, which allows us to control concurrency. Even better, we can use Test Schedulers in our Unit Tests to control time, allowing us to simulate Timeouts, race conditions etc.
These are some quick examples to demonstrate what is possible. There are many more operators within the Rx framework to cater for all types of scenarios and the composability of Rx means you can easily combine operators to define the behaviour you need. It’s also easy to create your own reusable operators (e.g. RetryAfterDelay).
In summary, Rx can do everything than Promises can do, and far far more. I suspect in the next couple of years there'll be a continued shift towards Rx instead of Promises.
For further reading, I'd recommend taking a look at the section on Observables in the Angular 2 guide.
as said in Angular 2 guid
Converting to a Promise is often a good choice when you want to fetch a single chunk of data. so When you receive the data, you're done.
But in some cases requests aren't always done only once. You may start one request, cancel it, and make a different request before the server has
responded to the first request.
for example in a search component As the user types a name into a search box, you'll make repeated HTTP requests by that search query.
A request-cancel-new-request sequence is difficult to implement with
Promises, but easy with Observables.
so if your component gets data with only one request it's a good choice to use Promise but if it has a chain of request-cancel-new request you should use observable
Observables are often compared to promises. Here are some key differences:
Observables are declarative; computation does not start until subscription. Promises execute immediately on creation. This makes observables useful for defining recipes that can be run whenever you need the result.
Observables provide many values. Promises provide one. This makes observables useful for getting multiple values over time.
Observables differentiate between chaining and subscription. Promises only have .then() clauses. This makes observables useful for creating complex transformation recipes to be used by other part of the system, without causing the work to be executed.
Observables subscribe() is responsible for handling errors. Promises push errors to the child promises. This makes observables useful for centralized and predictable error handling.
Best explanation by angular on official website :
https://angular.io/guide/comparing-observables
Observables VS. Promises (by Jeremy Vilken)
In addition to new syntax, observables are a newer pattern for JavaScript applications to
manage asynchronous activities. They’re also a draft for a feature to be natively implemented in the JavaScript language so it has weight behind the pattern. RxJS is the
library we’ll use to help us implement observables in our applications.
Promises are another construct to help deal with asynchronous calls, which are useful
for making API requests, for example. Promises have a major limitation in that they’re
only useful for one call cycle. For example, if you wanted to have a promise return a
value on an event like a user click, that promise would resolve on the first click. But you might be interested in handling every user click action. Normally, you’d use an event
listener for this, and that allows you to handle events over time. This is an important distinction: Observables are like event handlers in that they continue to process data over
time and allow you to continuously handle that stream of data.
When you understand Observables correctly, the differences to Promises are pretty obvious.
The best way to demystify a convoluted concept is to implement it from scratch. Here is an almost purely functional Observable implementation and an example, that wouldn't work with Promises:
/*** Observable type ***/
// type constructor (of a product type)
const proType = name => cons => {
const f = (k, ...args) =>
Object.defineProperties({["run" + name]: k}, {
[Symbol.toStringTag]: {value: name},
[Symbol("args")]: {value: args}
});
return cons(f);
};
// value constructor
const Observable = proType("Observable")
(Observable => k => Observable(k));
/*** Observer factory ***/
const Observer = observer => {
let isUnsubscribed = false;
return {
next: function(x) {
if (isUnsubscribed)
throw new Error("unsubscribed");
else {
try {
return observer.next(x);
}
catch(e) {
isUnsubscribed = true;
this.cancel();
throw e;
}
}
},
error: function(e) {
if (isUnsubscribed)
throw new Error("unsubscribed");
else {
try {
return observer.error(e);
}
catch(e_) {
isUnsubscribed = true;
this.cancel();
throw e_;
}
}
},
complete: function() {
if (isUnsubscribed)
throw new Error("unsubscribed");
else {
try {
const r = observer.complete();
this.cancel();
return r;
}
catch(e) {
isUnsubscribed = true;
cancel();
throw e;
}
}
}
};
};
/*** combinators + auxiliary functions ***/
const subscribe = observable => handlers => {
const observer = Observer(handlers),
cancel = observable.runObservable(observer);
observer.cancel = cancel;
return cancel;
};
const obsMap = f => observable =>
Observable(observer => {
const mapObserver = {
next: x => observer.next(f(x)),
error: e => observer.error(e),
complete: () => observer.complete()
};
return observable.runObservable(mapObserver);
});
/*** main ***/
// create an Observable instance
const numStream = Observable(observer => {
let i = 0;
const timer = setInterval(() => {
observer.next(i++);
}, 1000);
return () => clearTimeout(timer);
});
// map a function over it
const squaredNumStream =
obsMap(x => x * x) (numStream);
// run the observable
const cancel = subscribe(squaredNumStream) ({
next: x => console.log(x),
error: e => console.error(e),
complete: () => console.log("finished")
});
// cancel it
setTimeout(cancel, 11000);
In the example above the Observable squaredNumStream emits a stream of theoretically infinite values asynchronously. You cannot do this with Promises, because they represent a single future value.
I could have easily subscribed to another squaredNumStream without both instances interfering with each other. This is because Observables are unicast, whereas Promises are multicast.
squaredNumStream doesn't run at declaration time, but only after subscription, because Observables are lazily evaluated. Promises on the other hand are eagerly evaluated that is, they start running as soon as you create them.
And finally, Observables are cancelable by design, whereas Promises are hard to cancel due to there unicast semantics.