如何在每次观察到其他可观察变化时获得可观察的变化

时间:2017-07-28 21:51:10

标签: typescript observable rxjs5

问题

我有一个看起来像这样的服务:

DogService { 
    public getSelectedDog(): Observable<Uuid> {...}
    public getDog(dogUuid: Uuid): Observable<Dog> {...}
}

我想创建一个始终包含我选择的狗的Observable,即Observable<Dog>

到目前为止我尝试了什么

目前我正在做的是:

let selectedDog: Observable<Dog> =  dogService.getSelectedDog().flatMap( selectedDog => {
    return dogService.getDog( selectedDog );
});

然后您可以订阅所选狗的更改,如下所示:

selectedDog.subscribe( dog => console.log( 'dog: ", dog.name, dog.mood );

不幸的是,这似乎并没有像我预期的那样发挥作用。 selectedDog仅可观察 当狗本身发生变化时,当选定的狗改变时不会触发。

例如,假设我们执行以下操作:

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'

不幸的是,如果我更新狗,控制台无法登录:

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.

问题:如果选择或选定的狗发生变化,我该如何创建Observable<Dog>

1 个答案:

答案 0 :(得分:1)

您的代码应该有效,因此我怀疑您的服务存在问题。我有一些代码来证明它原则上应该可以工作。

您应该纠正的一个错误是您使用的是flatMap,但应该使用switchMap。问题是flatMap会将每个流合并到您的流中,无论您何时选择新的狗,这意味着您将不断获得您不想要的以前选定的狗的更新。所以这是我正在谈论的代码:

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

每隔5秒选择一只新狗,每只狗每隔1秒或半秒发送一次更新。同时尝试使用flatMap代替switchMap,您将看到我在说什么。