Reputation: 27241
I have a service that looks like this:
DogService {
public getSelectedDog(): Observable<Uuid> {...}
public getDog(dogUuid: Uuid): Observable<Dog> {...}
}
I would like to create an Observable that always contains my selected dog, ie Observable<Dog>
.
Currently what I am doing is this:
let selectedDog: Observable<Dog> = dogService.getSelectedDog().flatMap( selectedDog => {
return dogService.getDog( selectedDog );
});
Then you can subscribe to changes in the selected dog like this:
selectedDog.subscribe( dog => console.log( 'dog: ", dog.name, dog.mood );
Unfortunatly, this doesn't seem to work the way I expected it to. The selectedDog observable only fires when the selectedDog has changed by not when the dog itself changes.
So for example lets say that we do the following:
const dog1: Dog = new Dog( '1', // uuid
'Shadow', // name
'happy' // mood
);
const dog2: Dog = new Dog( '2', // uuid
'Barky', // name
'Angry' // mood
);
// Fires the getDog observable
dogService.addDog( dog1 );
// Fires the getDog observable
dogService.addDog( dog2 );
// Fires the getSelectedDogObservable
dogService.selectDog( dog1.uuid )
// --- Now in console.log we will see: 'dog: Shadow happy'
Unfortunatly, if I update the dog, the console doesn't get logged to:
const updatedDog1: Dog = new Dog( '1', // uuid
'Shadow', // name
'SAD' // mood
);
// Fires the getDog observable
dogService.updateDog( updatedDog1 );
// --- the console.log doesn't get invoked. Crap.
Question: How can I create Observable<Dog>
that will fire whenever the selection or selected dog changes?
Upvotes: 0
Views: 393
Reputation: 20009
Your code should work, so I suspect a problem in your service. I have some code to demonstrate that in principle it should work.
One mistake you should correct though is that you are using flatMap
, but should be using switchMap
. The thing is that flatMap
will merge every stream into your stream regardless of when you select a new dog, meaning you will keep getting updates of the previous selected dogs, which you don't want. So here is the code I was talking about:
var dogs = [
Rx.Observable.timer(0, 500).map(() => 'barky'),
Rx.Observable.timer(0, 1000).map(() => 'cuddles')
];
var selectedDog = 0;
var dogSelector = Rx.Observable
.timer(0, 5000)
.map(_ => {
selectedDog = (selectedDog ? 0 : 1);
return selectedDog;
})
.switchMap(i => dogs[i]);
dogSelector.subscribe(dog => console.log(`Doggy: ${dog}`))
http://jsbin.com/haqutehajo/1/edit?js,console
A new dog is selected every 5 second and each dog sends an update every 1 or half a second respectively. Also try flatMap
instead of switchMap
and you will see what I am talking about.
Upvotes: 1