Angular RxJS动态分配按钮的多个订阅

Angular RxJS动态分配按钮的多个订阅,angular,rxjs,observable,angular2-observables,Angular,Rxjs,Observable,Angular2 Observables,假设我有一个角2分量,如下所示: import { Component, AfterViewInit, ViewChildren, QueryList, ElementRef } from '@angular/core'; import { Observable } from 'rxjs/Rx'; import {ApiService} from './my.service' @Component({ selector: 'my-component', template: ` &

假设我有一个角2分量,如下所示:

import { Component, AfterViewInit, ViewChildren, QueryList, ElementRef } from '@angular/core';
import { Observable } from 'rxjs/Rx';
import {ApiService} from './my.service'
@Component({
  selector: 'my-component',
  template: `
    <div class='button0' [ngClass]="{selected: selection === 0}" #button>Hello World</div>
    <div class='button1'  [ngClass]="{selected: selection === 1}" #button>Hello World</div>
  `,
  styles: [`
  .selected {
    color: red;
  }
  `],
  providers: [ApiService]
})
export class MyComponent implements AfterViewInit { 
  selection = 0;
  @ViewChildren('button') buttons: QueryList<ElementRef>;
  buttonObservables:any[] = null;

  constructor(private api: ApiService) {}

  updateServer(index) {
    api.requestsExample(index)
      .then((result) => {
        //update other divs and stuff
      }
  }


  updateColor(index) {
    this.selection = index;
  }

  ngAfterViewInit () {
    this.buttonObservables = this.buttons.map((button) => Observable
      .fromEvent<MouseEvent>(button.nativeElement, 'click'));

    this.buttonObservables.map((observable) => {
      observable.throttleTime(2000).subscribe((event:MouseEvent) => {
          const element:Element = event.target as Element;
        this.updateServer(element.classList[1].match(/\d+/g));
      })
    });

    this.buttonObservables.map((observable) => {
      observable.subscribe((event:MouseEvent) => {
        const element:Element = event.target as Element;
        this.updateColor(element.classList[1].match(/\d+/g));
      })
    });
  }
}
从'@angular/core'导入{Component,AfterViewInit,ViewChildren,QueryList,ElementRef};
从'rxjs/Rx'导入{Observable};
从“/my.service”导入{ApiService}
@组成部分({
选择器:“我的组件”,
模板:`
你好,世界
你好,世界
`,
风格:[`
.选定{
颜色:红色;
}
`],
供应商:[ApiService]
})
导出类MyComponent实现AfterViewInit{
选择=0;
@ViewChildren(“按钮”)按钮:QueryList;
ButtonObjectables:any[]=null;
构造函数(私有api:ApiService){}
更新服务器(索引){
api.requestsExample(索引)
。然后((结果)=>{
//更新其他div和内容
}
}
更新颜色(索引){
这个选择=索引;
}
ngAfterViewInit(){
this.buttonObservables=this.buttons.map((按钮)=>Observable
.fromEvent(button.nativeElement,'click');
this.buttonObservables.map((可观察)=>{
observable.throttleTime(2000).subscribe((事件:MouseEvent)=>{
常量元素:元素=event.target作为元素;
this.updateServer(element.classList[1].match(/\d+/g));
})
});
this.buttonObservables.map((可观察)=>{
可观察。订阅((事件:MouseEvent)=>{
常量元素:元素=event.target作为元素;
this.updateColor(element.classList[1].match(/\d+/g));
})
});
}
}
其中ApiService.requestsExample

是一个异步带注释的函数,它发出请求并返回响应

代码基本正常(例如,请求被限制,按钮混搭不会导致太多请求,颜色仍然会改变)

我正在努力解决以下问题: 1) 我想保证最后触发的结果是接受响应的结果(假设响应返回),然后按时间顺序返回。由于请求是异步的,我不知道如何实现这一点? 2) (推论)为了防止更新时出现闪烁,我还希望在稍后的结果返回时(基于问题顺序而不是响应顺序)放弃从服务器返回的任何结果。 3) 一旦最后一个当前活动的请求返回,我想放弃所有正在进行的观察,因为我不再关心它们

因此,基本上,如果用户将两个按钮混合20秒,我希望发出10ish请求,但除了切换按钮颜色外,更新UI一次,并将其设置为正确的值

此外,我非常希望得到任何反馈,了解是否有更好的方法通过可观测数据实现这一结果(或者即使可观测数据是这项工作的正确工具!)

让我们解释以下示例:

  • 您希望使
    updateServer
    成为反应式计算的一部分,因此您要使它返回一个可观察值
  • 由于您以相同的方式处理所有单击,因此将所有来自不同按钮的单击合并是有意义的
  • 由于您只使用按钮的索引进行计算,因此有必要单击
    将其映射到
  • 您可以使用
    do
    执行即时
    updateColor
    作为副作用
  • debounceTime(1000)
    仅在一秒钟后发出一次点击,而没有其他点击。我认为这比节流要好,因为如果用户进行多次快速点击,您不想进行不必要的网络呼叫。只有最后一个
  • 由于您希望在新的单击出现时取消以前的
    updateServer
    ,因此使用
    switchMap
    是有意义的。它将单击映射到一个新的
    updateServer
    observable,然后中止该操作,并在新的单击到达时切换到一个新的
  • 由于您希望忽略第一次
    更新服务器之后的所有进一步单击,或者这就是我对3的理解),
    获取(1)
    将获取一个结果,然后完成整个链
updateServer(索引){
返回可观察的.fromPromise(api.requestsExample(索引))
}
这
.按钮不可维护
.mergeAll()
.map(ev=>ev.target.classList[1]。匹配(/\d+/g))
.do(idx=>this.updateColor(idx))
.debounceTime(1000)
.switchMap(idx=>this.updateServer(idx))
.采取(1)
.订阅(结果=>{
//更新其他div
})
让我们解释下面的示例:

  • 您希望使
    updateServer
    成为反应式计算的一部分,因此您要使它返回一个可观察值
  • 由于您以相同的方式处理所有单击,因此将所有来自不同按钮的单击合并是有意义的
  • 由于您只使用按钮的索引进行计算,因此有必要单击
    将其映射到
  • 您可以使用
    do
    执行即时
    updateColor
    作为副作用
  • debounceTime(1000)
    仅在一秒钟后发出一次点击,而没有其他点击。我认为这比节流要好,因为如果用户进行多次快速点击,您不想进行不必要的网络呼叫。只有最后一个
  • 由于您希望在新的单击出现时取消以前的
    updateServer
    ,因此使用
    switchMap
    是有意义的。它将单击映射到一个新的
    updateServer
    observable,然后中止该操作,并在新的单击到达时切换到一个新的
  • 由于您希望忽略第一次
    更新服务器之后的所有进一步单击,或者这就是我对3的理解),
    获取(1)
    将获取一个结果,然后完成整个链
updateServer(索引){
返回可观察的.fromPromise(api.requestsExample(索引))
}
这
.按钮不可维护
.mergeAll()
.map(ev=>ev.target.classList[1]。匹配(/\d+/g))
.do(idx=>this.updateColor(idx))
.debounceTime(1000)