Is there any way to chain several observables but allowing the chain to complete at any time? I have three Observables, they all return booleans. However, I would only want to progress to the next observable in the chain if the current observable is false. The observables must progress upon the completion of the last one and where the completed value is false. Is this possible?
You can setup an observable that control the flow and complete it when you are done. Also use zip operator - it will complete the whole flow if one of the observable(in our case the control one) is completed.
let control$ = new Rx.Subject();
let data$ = Rx.Observable.interval()
.map(x => x<10?true:false)
.do(flag => {
if(flag) control$.next(true);
else control$.complete();
});
Rx.Observable.zip(data$.filter(x=>x), control$.startWith(true), (x,y)=>x)
.subscribe(x=>console.log(x))
Related
How do I know when an Observable producer is async or sync?
An sync example:
Observable.of([1, 2, 3])
another async example (ngrx Store, see here)
this.store.take(1);
And now an obvious async example:
this.http.get(restUrl)
I fully understand how this works, and that some Observables can be sync and others Async. What I don't understand is how i can tell the difference in advance? Is there for example an obvious interface on the producer that tells me that it will be async?
tl;dr
The main reason this question has come up is because of the answer from the link above (here).
#Sasxa has (correctly) answered that we can use a synchronous call to get the latest value from the ngrx store:
function getState(store: Store<State>): State {
let state: State;
store.take(1).subscribe(s => state = s);
return state;
}
However knowing that observables are usually asynchronous, I saw this and immediately thought RACE CONDITION! the method could return an undefined value before subscribe has called back the function.
I've debugged through the internals of Store and Observable and this example is indeed synchronous, but how should I have known that? For those that know ngrx, the select method of store (used to get the latest values) is asynchronous, without a doubt, as this is what gives us the reactive gui, which is why I came to the assumption I did.
It means that I cannot refactor the code above as follows:
function getLatest(observable: Observable): any {
let obj: any;
observable.take(1).subscribe(latest => obj = latest);
return obj;
}
I could call this with any Observable and it would work for synchronous producers - it may even work SOME OF THE TIME for async producers, but this is without a doubt a race condition if an async observable is passed in.
It is possible to determine if an observable is asynchronous for sure if was directly scheduled with asynchronous scheduler (Scheduler.async or Scheduler.asap), it's exposed as foo$.scheduler:
let schedulers = [null, Scheduler.asap];
let randomScheduler = schedulers[~~(Math.random()*2)]
let foo$ = Observable.of('foo', randomScheduler);
This information becomes even less available when foo$ is processed further, e.g. chained with other operators.
And it's impossible to determine if values will be produced synchronously (on same tick) or asynchronously because this depends on observable internals:
let foo$ = new Observable(observer => {
if (~~(Math.random()*2))
setTimeout(() => observer.next('foo'));
else
observer.next('foo');
});
TL;DR: it's impossible to know this for sure.
It is hard to figure out whether an observable you get is sync or async (imagine you get observables return from a thrid party library). That's why you write it in a fashion that the execution order is controlled and predictable.
That's also why there are operators like concat, combineLatest, forkjoin, switchMap, race, merge to help you get the order and performance right for different scenario
I wish the answer was forkJoin / Promises.all, but it's a bit more, please bear with me.
I have a source of promises, that can arrive in random order, and I need some way to say "when all promises that arrived so far are done, let me know".
In a Promise based solution, I thought initially of using Promise.all but promises can be still "arriving" while others haven't completed. Interestingly there is a neat workaround for an "iterable Promise.all" at https://stackoverflow.com/a/37819138/239168
I'm trying to do this the Rx way. After reading the docs for a little, I think forkJoin is the Promise.all equivalent, however, same problem, there is no point in time where I can safely call forkJoin or Promise.all as there can always be one more added while another is still pending... Since I probably make no sense by now, I thought I'll ask for some guidance.
Setup
(hold your laughs if it's silly, I'm new to Rx...)
I have a Subject, and I want to know when all of the promises in it are complete... also it can always get new added promises at any time...
private promiseSource = new Subject<Promise<any>>();
promises$ = this.promiseSource.asObservable();
Every time a new promise "arrives", I'm just adding it to the subject
this.promiseSource.next(somePromise);
What I would like to magically happen is - have the subject "complete" whenever it holds only completed promises.
e.g.
promises$.magicFlatMapForkJoinConcatMapTrickery().subscribe({
next: x => ...,
error: err => ...,
complete: () => {
console.log('all promises we got so far are done');
// nice to have, I want this to keep "listening" for new promises
promiseSource.youAreNotREALYCompletePleaseReset();
}
});
Or in other words, I have an observable of async actions, if we take a look at the content, we can see overlapping async actions, I want to know when there is no overlap e.g.
|<-async action 1->| |<-async action 3->|
|<-async action 2->| |<-async action 4->|
/\ /\
find this gap
if these were for example http calls, I'm asking basically - tell me when there are no open http calls.
tl;dr
how to implement this Promises based answer in an RxJS world...
https://stackoverflow.com/a/37819138/239168
If I'm interpreting your question correctly, you are only interested in a signal that indicates whether or not there are pending promises.
It's pretty easy to use merge and scan to create an observable that emits a count of pending promises and, from that, you should be able to create whatever signals you like.
Basically, every time the subject emits a promise, the count of pending promises should be incremented. And each time one of those promises resolves, the count can be decremented.
const promises = new Rx.Subject();
const pendingCount = Rx.Observable
.merge(
promises.mapTo(1),
promises.mergeMap(p => Rx.Observable.from(p).mapTo(-1))
)
.scan((acc, value) => acc + value, 0)
.do(count => console.log(`${count} pending promise(s)`));
const doneSignal = pendingCount
.filter(count => count === 0)
.mapTo("done");
doneSignal.subscribe(signal => console.log(signal));
const timeoutPromise = (delay) => new Promise(resolve => setTimeout(resolve, delay));
promises.next(timeoutPromise(200));
setTimeout(() => promises.next(timeoutPromise(200)), 100);
setTimeout(() => promises.next(timeoutPromise(200)), 300);
setTimeout(() => promises.next(timeoutPromise(200)), 700);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://unpkg.com/rxjs#5/bundles/Rx.min.js"></script>
I can think of a fairly straightforward way of doing this based on a previous answer. You could use fromPromise to turn your Subject<Promise<any>> into a Subject<Observable<any>>, and then you could use the active function described in this answer to reduce that down to an observable of active observables. Once you've got that, you can phrase your query as "when the array of active streams becomes empty", which can be done with a simple filter, e.g.:
active(yourSubjectOfObservables).filter(x => x.length === 0).subscribe(() => {
// here we are, all complete
});
This will trigger each time the number of active streams transitions to zero, so if you only want the first time, place a .take(1) or .first between the filter and the subscribe.
Probably not the prettiest solution, but it's conceptually simple.
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).
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.
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.