Last active
April 10, 2017 11:24
-
-
Save RomkeVdMeulen/92d2127827098499762eceaed63eeb3a to your computer and use it in GitHub Desktop.
Simple poller library built in TypeScipt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {BackendService} from "./backend"; | |
export class PollerService { | |
constructor(private backendService: BackendService) { | |
} | |
static readonly INTERVAL = { | |
SHORT: 1000, | |
STANDARD: 2000, | |
LONG: 5000, | |
}; | |
makeBasicPoller(resourceUrl: string, interval = PollerService.INTERVAL.STANDARD) { | |
return new BasicPoller(this.backendService, resourceUrl, interval); | |
} | |
makeListPoller(resourceUrl: string, resourceIds: any[], interval = PollerService.INTERVAL.STANDARD) { | |
return new ListPoller(this.backendService, resourceUrl, resourceIds, interval); | |
} | |
} | |
export interface Poller { | |
interval: number; | |
readonly started: boolean; | |
start(callback: Function): void; | |
stop(): void; | |
} | |
abstract class PollerBase implements Poller { | |
protected timeoutId: number | undefined; | |
constructor(protected backendService: BackendService, protected resourceUrl: string, public interval: number) { | |
} | |
abstract start(callback: Function): void; | |
stop() { | |
if (this.timeoutId) { | |
clearTimeout(this.timeoutId); | |
this.timeoutId = undefined; | |
} | |
} | |
get started() { | |
return this.timeoutId !== undefined; | |
} | |
} | |
/** | |
* Basic Poller: calls the callback with every response. If the callback returns | |
* (a promise that resolves to) false the poller is stopped. In all other cases | |
* the poller continues. | |
*/ | |
export class BasicPoller extends PollerBase { | |
private callback: (resource: any) => any; | |
constructor(backendService: BackendService, resourceUrl: string, interval: number) { | |
super(backendService, resourceUrl, interval); | |
} | |
start(callback: (resource: any) => any) { | |
this.callback = callback; | |
this.schedulePoll(); | |
} | |
private schedulePoll() { | |
this.timeoutId = window.setTimeout( | |
async () => { | |
if (await this.poll() !== false) { | |
this.schedulePoll(); | |
} | |
}, | |
this.interval, | |
); | |
} | |
private async poll() { | |
const response = await this.backendService.get(this.resourceUrl); | |
return this.callback(response); | |
} | |
} | |
/** | |
* Poller for a list of resources. Keeps a list of IDs of resources to be | |
* retrieved. Builds query string automatically, updated every time resources | |
* are returned. Automatically stops polling once all resource have been | |
* received. | |
*/ | |
export class ListPoller extends PollerBase { | |
private identifier = "id"; | |
private callback: (resource: any) => void; | |
constructor(backendService: BackendService, resourceUrl: string, private resourceIds: any[], interval: number) { | |
super(backendService, resourceUrl, interval); | |
} | |
start(callback: (resource: any) => void) { | |
this.callback = callback; | |
if (this.resourceIds.length > 0) { | |
this.schedulePoll(); | |
} | |
} | |
setIdentifier(identifier: string) { | |
this.identifier = identifier; | |
} | |
private schedulePoll() { | |
this.timeoutId = window.setTimeout( | |
async () => { | |
await this.poll(); | |
if (this.resourceIds.length > 0) { | |
this.schedulePoll(); | |
} | |
}, | |
this.interval, | |
); | |
} | |
private async poll() { | |
const baseUrl = this.resourceUrl + (!this.resourceUrl.includes("?") ? "?" : "&"); | |
const response = await this.backendService.get(baseUrl + this.buildQuery(this.resourceIds)); | |
if (response instanceof Array) { | |
(<any[]> response).forEach(this.callback); | |
const responseIds = this.extractIds(response); | |
this.resourceIds = this.resourceIds.filter(id => !responseIds.includes(id)); | |
} | |
} | |
private buildQuery(resourceIDs: any[]) { | |
const ident = encodeURIComponent(this.identifier); | |
return resourceIDs | |
.map(id => ident + "=" + encodeURIComponent(id)) | |
.join("&"); | |
} | |
private extractIds(result: any[]) { | |
return result.map(resource => resource[this.identifier]); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment