Created
January 4, 2023 08:42
-
-
Save muke1908/c9e3fbf4b91af0c143d8108f2541396b to your computer and use it in GitHub Desktop.
Run timer on webworker for BG ops.
This file contains 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
/* | |
const timer = new WorkerBasedTimer(); | |
const id = timer.setInterval(()=> { | |
// do something | |
}, 200); | |
timer.clearInterval(id); | |
*/ | |
type TimerData = { | |
id: number; | |
callback: (arg: any) => void; | |
args: any; | |
}; | |
export class WorkerBasedTimer { | |
private readonly timerId = 1; | |
private timerData: TimerData; | |
private doWork: Worker; | |
private timeout: number; | |
private isTimerClearing: boolean; | |
private deferredTimerOp: { | |
callback: TimerData['callback'], | |
timeout: number, | |
args?: any | |
} | |
constructor() { | |
this.createWorker(); | |
} | |
public static isSupported(): boolean { | |
} | |
public setInterval(callback: TimerData['callback'], timeout: number, args?: any): number { | |
// deffer the timer creation until the previously created timer is cleared on worker. | |
if(this.isTimerClearing) { | |
this.deferredTimerOp = { | |
callback, | |
timeout, | |
args | |
} | |
return this.timerId; | |
} | |
if (this.timerData) { | |
return null; | |
} | |
this.timerData = { | |
id: this.timerId, | |
callback, | |
args, | |
}; | |
this.timeout = timeout; | |
this.doWork.postMessage({ next: true, id: this.timerId, ms: this.timeout }); | |
return this.timerId; | |
} | |
public clearInterval(id: number): void { | |
if (!id) { | |
return; | |
} | |
this.isTimerClearing = true; | |
this.doWork.postMessage({ stop: true, id }); | |
} | |
public disposeTimerWorker() { | |
if (!this.doWork) { | |
return; | |
} | |
this.timerData = null; | |
this.doWork.removeEventListener('message', this.workerMessageHandler); | |
this.doWork.removeEventListener('error', this.workerErrorHandler); | |
this.doWork.terminate(); | |
this.doWork = null; | |
} | |
private readonly workerMessageHandler = (event: MessageEvent): any => { | |
switch (event.data.type) { | |
case 'ping': | |
return this.onPing(); | |
case 'setIntervalCompleted': | |
return this.onSetIntervalCompleted(event.data.id); | |
case 'clearTimeoutCompleted': | |
return this.onTimeoutClearCompleted(event.data.id); | |
default: | |
return undefined; | |
} | |
}; | |
private readonly workerErrorHandler = (error: ErrorEvent): void => { | |
}; | |
private onSetIntervalCompleted(id: number): void { | |
} | |
private onTimeoutClearCompleted(id: number): void { | |
this.timerData = null; | |
this.isTimerClearing = false; | |
if(this.deferredTimerOp) { | |
const { callback, timeout, args } = this.deferredTimerOp; | |
this.setInterval(callback, timeout, args); | |
this.deferredTimerOp = null; | |
} | |
} | |
private onPing(): void { | |
if (this.timerData?.callback) { | |
this.timerData.callback(this.timerData.args); | |
this.doWork.postMessage({ next: true, id: this.timerId, ms: this.timeout }); | |
} | |
} | |
private createWorker(): void { | |
try { | |
// Code to execute in the worker | |
const blob = new Blob( | |
[ | |
`'use strict'; | |
var internalId; | |
var externalId; | |
(function () { | |
onmessage = function (event) { | |
if (event.data.next) { | |
clearTimeout(internalId); | |
externalId = event.data.id; | |
internalId = setTimeout(function () { | |
postMessage({ type: 'ping', id: externalId }); | |
}, event.data.ms); | |
} else if (event.data.stop) { | |
if (event.data.id === externalId) { | |
clearTimeout(internalId); | |
} | |
postMessage({ type: 'clearTimeoutCompleted', id: externalId }); | |
} | |
}; | |
})();`, | |
], | |
{ type: 'text/javascript' }, | |
); | |
// Create a worker to process timers | |
this.doWork = new uaa.window.Worker(uaa.window.URL.createObjectURL(blob)); | |
this.doWork.addEventListener('message', this.workerMessageHandler); | |
this.doWork.addEventListener('error', this.workerErrorHandler); | |
} catch (error) { | |
throw error; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment