Typescript RxJS中切换订阅的最优雅方式

Typescript RxJS中切换订阅的最优雅方式,typescript,rxjs,Typescript,Rxjs,由于我已经是一名经验丰富的.NET开发人员,我正在学习新技术,我很好奇您如何在TypeScript+RxJS中解决这个问题。 比如说,我有多个列(字段),我正在观察它们的值的变化。我还有一个开关,它有一组列要观察——在这个例子中是1,2,3;A、 B,C和X,Y,Z 每次我必须切换时,我都希望从以前的组中删除订阅,并为新组创建订阅。代码如下所示: const log = (cid: string) => console.info(`${cid} changed`); this.subsc

由于我已经是一名经验丰富的.NET开发人员,我正在学习新技术,我很好奇您如何在TypeScript+RxJS中解决这个问题。 比如说,我有多个列(字段),我正在观察它们的值的变化。我还有一个开关,它有一组列要观察——在这个例子中是1,2,3;A、 B,C和X,Y,Z

每次我必须切换时,我都希望从以前的组中删除订阅,并为新组创建订阅。代码如下所示:

const log = (cid: string) => console.info(`${cid} changed`);

this.subscriptions.add(this.observeValueChanges("column 1").subscribe(log));
this.subscriptions.add(this.observeValueChanges("column 2").subscribe(log));
this.subscriptions.add(this.observeValueChanges("column 3").subscribe(log));

//Switching to another columns collection - I don't want previous subscriptions anymore
this.subscriptions.unsubscribe();
this.subscriptions.add(this.observeValueChanges("column A").subscribe(log));
this.subscriptions.add(this.observeValueChanges("column B").subscribe(log));
this.subscriptions.add(this.observeValueChanges("column C").subscribe(log));

//Switching to another columns collection - I don't want previous subscriptions anymore
this.subscriptions.unsubscribe();
this.subscriptions.add(this.observeValueChanges("column X").subscribe(log));
this.subscriptions.add(this.observeValueChanges("column Y").subscribe(log));
this.subscriptions.add(this.observeValueChanges("column Z").subscribe(log));
供参考:

private subscriptions: Subscription = new Subscription();

observeValueChanges(columnId:string):可观察{
返回计时器(0,1000).pipe(map(=>columnId),publish(),refCount());
}
我可以通过用订阅数组替换订阅对象使其工作,切换后-我可以从数组中全部取消订阅(而不是添加-我可以推送)。
你喜欢什么?我对将“开关信号”设置为可观察状态没有问题。

有趣的是,您使用了“开关”一词,因为您正在寻找的操作员被称为

每当接收到一个新值时,它都会将其“映射”到一个可观测值,并从以前的源“切换”

switchMap
是一个“”,它为您做了几件好事:

  • 将传入值映射到另一个可观察值
  • 订阅它,因此将发出其值
  • 自动管理从这些“内部订阅”取消订阅
  • 我已经在这里创建了一个工作示例


    这是一个很好的答案,我完全可以在我的解决方案中使用它!好东西!很高兴有帮助!:-)
    observeValueChanges(columnId: string): Observable<any> {
         return timer(0, 1000).pipe(map(_ => columnId), publish(), refCount());
    }
    
    import { fromEvent } from 'rxjs'; 
    import { tap, map, switchMap } from 'rxjs/operators';
    
    const group0 = document.querySelectorAll('.group0');
    const group1 = document.querySelectorAll('.group1');
    
    const selectedGroup = document.querySelectorAll('.selected-group');
    
    // Array of possible sources to "switch" between
    //
    // [fromEvent] Creates an observable that emits DOM
    //             events for the specified elements.
    //
    // [map] Just maps the event to the target value.
    const sources$ = [
      fromEvent(group0, 'keyup').pipe(map(event => event.target['value'])),
      fromEvent(group1, 'keyup').pipe(map(event => event.target['value']))
    ];
    
    // selectedGroup$ emits the value of the selected radio button which
    // for this example is conveniently the group's index in the array.
    const selectedGroup$ = fromEvent(selectedGroup, 'change').pipe(
      map(event => event.target['value'])
    );
    
    // source$ starts with the emission of selectedGroup$. Then we
    // use [switchMap] to "switch" our source observable and map
    // it to a new observable source. Then switchMap will
    // automatically unsubscribe from the previous one.
    const source$ = selectedGroup$.pipe(
      switchMap(groupIndex => sources$[groupIndex])
    )
    
    // Notice we only need a single subscription!
    source$.subscribe(console.log);