假设我有一个角度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));
})
});
}
}
其中ApiService.requestsExample
是一个异步注释函数,它发出请求并返回响应。
关于工作的代码(例如请求被限制,按钮混合不会导致请求太多,颜色仍然会改变)
我正在努力想办法处理下面的边框: 1)我想保证最后触发的结果是接受响应的结果(假设响应返回),然后按时间顺序返回。由于请求是异步的,我不确定如何实现这一点? 2)(推论)为了防止更新闪烁,我还想放弃一旦后来的结果返回时从服务器返回的任何结果(基于问题顺序而不是响应顺序)。 3)一旦最后一个当前的实时请求返回,我想丢弃所有正在进行的观察,因为我不再关心它们。
所以基本上,如果用户将两个按钮混合20秒,我会期望发出10个请求,但除了切换按钮颜色外,更新UI一次,并更新到正确的值。
此外,我很想知道是否有更好的方法可以通过Observables实现这一结果(或者即使可观察对象是这项工作的正确工具!)
答案 0 :(得分:2)
让我们解释下面的RxJS 5示例:
updateServer
成为反应计算的一部分,所以你让它返回一个可观察的。mergeAll
来自不同按钮的所有点击都是有意义的。map
点击就可以了。updateColor
作为副作用立即执行do
。debounceTime(1000)
仅在传递一秒后发出点击而没有其他点击。我认为这比Throttle
好,因为如果用户进行多次快速点击,您就不想进行不必要的网络通话。只有最后一个。updateServer
,因此使用switchMap
是有意义的。它将点击映射到新的updateServer
可观察对象然后中止它,并在新点击到达时切换到新的点击。updateServer
之后的所有进一步点击,或者这是我理解的方式3),take(1)
将获得一个结果,然后完成整个链。updateServer(index) {
return Observable.fromPromise(api.requestsExample(index))
}
this
.buttonObservables
.mergeAll()
.map(ev => ev.target.classList[1].match(/\d+/g))
.do(idx => this.updateColor(idx))
.debounceTime(1000)
.switchMap(idx => this.updateServer(idx))
.take(1)
.subscribe(result => {
// update other divs
})