Say I have an angular 2 component like so:
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));
})
});
}
}
where ApiService.requestsExample
is an async annotated function which makes a request and returns a response.
The code just about works (e.g. requests are throttled, button mashing does not result in too many requests, colors still change)
I am struggling to figure out to handle the following edgecase: 1)I would like to guarantee that the result that was fired last is the one the response from which is accepted (assuming a response comes back), and then work back in chronological order. I am not sure how to achieve this due to the fact that requests are asynchronous? 2) (corollary)In order to prevent flicker on updating, I would also like to discard any results that come back from the server once a later result comes back (based on issue order rather than response order). 3) Once the last currently live request returns, I would like to discard all ongoing observables, as I no longer care about them.
So basically, if a user mashes the two buttons for 20 seconds, I would expect to make 10ish requests, but with the exception of toggling the button colors, update the UI once, and to the correct value.
Additionally I would just love any feedback on whether there is a better way to achieve this result with Observables (or even if observables are the right tool for this job!)