import { isUndefined } from 'lodash' ; const poll = require ( 'when/poll' ) ; let pollsMap = { } ; export interface ITaskWrapper { task : ( ) => Promise < any > ; resolver : Function ; rejecter : Function ; } export class Poll { public queue : ITaskWrapper [ ] = [ ] ; public poll : Promise < any > = null ; constructor ( private name , private delay = 200 , private debug = false ) { } public run ( ) { this . log ( 'add item to queue' , this . queue . length ) ; if ( ! this . isRunning ( ) && ! this . isEmpty ( ) ) { this . poll = poll ( ( ) => { this . log ( 'consume from queue' , this . queue . length ) ; let taskWrapper = this . queue . pop ( ) ; return taskWrapper . task . call ( taskWrapper ) . then ( taskWrapper . resolver , taskWrapper . rejecter ) ; } , this . delay , ( ) => this . isEmpty ( ) ) . then ( ( ) => this . poll = null ) ; } } public addToQueue ( task ) { let taskWrapper = { task : task , resolver : null , rejecter : null } ; this . queue . push ( taskWrapper ) ; let promiseSync = new Promise ( ( resolve , reject ) => { taskWrapper . resolver = resolve ; taskWrapper . rejecter = reject ; } ) ; this . run ( ) ; return promiseSync ; } public isRunning ( ) { return this . poll !== null ; } public isEmpty ( ) { return this . queue . length === 0 ; } private log ( ... args ) { if ( this . debug ) { console . log . apply ( console . log , [ 'Poll >' ] . concat ( args ) ) ; } } } export function syncedPoll ( namespace , task , delay = 200 ) { if ( isUndefined ( pollsMap [ namespace ] ) ) { pollsMap [ namespace ] = new Poll ( namespace , delay ) ; } return pollsMap [ namespace ] . addToQueue ( task ) ; }