2

I have a service with some methods, most of them require a certain callback to be completed before it can do its stuff. With Promises, in pseudo, it is very easy to do this:

ready = http.get(stuff); // Returns a promise, resolves after a while methodOne() { // methods sometimes called before promise resolves this.ready.then(_ => { // doStuff }); } methodTwo() { return this.ready.then(d => { // doOtherStuff }); } 

Basically I need to do the stuff, only when i'm sure the service is ready. I actually only need to check if it's ready (what methodOne is doing, just illustrating with methodTwo, that it's easy to more stuff as well).

I want to try and go all in on Observables, but for this specific case, I find it really hard to compete with a similar solution for Observables.

Promises will remember the value and know if it got resolved. An Observable is somewhat more complex and it seems that creating this same flow is troublesome. I need whatever is subscribing to the Observable, to known when it's ready. Some times the method is called early - before the Observable emits and sometimes late, after the Observable already emitted.

I have this right now, but it doesn't seem to work:

this.ready$ = someObservable // Will fire after a litle while but never finish - i only need the first to check though. .publishReplay(1).refCount(); // Trying to replay if subscription comes after emit. this.ready$.subscribe(_ => { // This will be called }); methodOne() { this.ready$.subscribe(_ => { // Not called }); }; 

Perhaps i misunderstood the use of publishReplay and refCount?

6
  • 1
    "Since I'm working on an Angular project, the preferred way is to go all in on Observables" Preferred by whom? With what justification? And what supporting data? Commented Aug 2, 2017 at 16:47
  • @T.J.Crowder I will edit my statement since it might be subjective, but I've seen it mentioned several places. stackoverflow.com/questions/37364973/… Commented Aug 2, 2017 at 16:48
  • I bit quick on the vote for close - I need a solution with Observables, the phrasing can (and was) changed so it's not longer opinion based. Commented Aug 2, 2017 at 16:51
  • 1
    "Are Observables really a good substitute for Promises" is, prima facie, asking for opinion. (It wasn't my close vote, btw.) If the question is really "How can I use Observables instead of Promises?" I'd edit the question title to say that. I'd also edit to make it much more concise. (And one person expressing an opinion in an SO answer does not qualify as a reasonable justification with supporting data.) Commented Aug 2, 2017 at 16:53
  • 1
    @T.J.Crowder Good point, title was changed. Commented Aug 2, 2017 at 16:55

1 Answer 1

3

I think what you're looking for is AsyncSubject. It mimics the promises behavior very well. Here is the description:

The AsyncSubject is a variant where only the last value of the Observable execution is sent to its observers, and only when the execution completes.

Here is how it can be used in your case:

subject = new AsyncSubject(); ready = streamOfData(stuff).first().subscribe(subject); methodOne() { return this.subject.asObservable(); } 

The subject subscribes to the underlying observable returned by the first operator and waits until it's complete. It collects all the subscribers but doesn't send any values to them. As soon as the underlying observable completes it remembers the value and sends it to the collected subscribers. All new future subscribers will be immediately passed this stored resolved value.

Here is the simple example that demonstrates that you can subscribe before or after the observable completes:

const subject = new AsyncSubject(); const o = subject.asObservable(); o.subscribe((v) => { console.log(v); }); interval(500).first().subscribe(subject); setTimeout(() => { o.subscribe((v) => { console.log(v); }); }, 2000); 
Sign up to request clarification or add additional context in comments.

9 Comments

I should mention that the example is not loading a http request - it really is a stream that never ends. I'll update my question to reflect this more clearly. I guess i could use a .first() on my observable... I'll try it out.
@PerHornshøj-Schierbeck, so how were you supposed to use promises with the stream that never ends? Promises is all about one resolved value.
I would wrap the first emit and resolve the promise then
@PerHornshøj-Schierbeck, okay, just use first() then. Updated my answer
This behaves excatly like my own attempt with replaySubject(1).refCount(). It works with promises (just tested), but both Observable examples only work if subscription (your methodOne) is called before the first/only emit. Come to think of it, calling .first() unsubscribes, perhaps that is why?
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.