Skip to content

Commit

Permalink
Merge c6b7a6c into 7ca9036
Browse files Browse the repository at this point in the history
  • Loading branch information
nev21 authored Mar 2, 2023
2 parents 7ca9036 + c6b7a6c commit 330d852
Show file tree
Hide file tree
Showing 7 changed files with 619 additions and 227 deletions.
137 changes: 107 additions & 30 deletions lib/src/timer/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@
* Licensed under the MIT license.
*/

import { objDefineProp } from "../object/define";

const REF = "ref";
const UNREF = "un" + REF as "unref";
const HAS_REF = "hasRef";
const ENABLED = "enabled";

/**
* A Timer handler which is returned from {@link scheduleTimeout} which contains functions to
* cancel or restart (refresh) the timeout function.
Expand Down Expand Up @@ -92,6 +99,55 @@ export interface ITimerHandler {
* ```
*/
hasRef(): boolean;

/**
* Gets or Sets a flag indicating if the underlying timer is currently enabled and running.
* Setting the enabled flag to the same as it's current value has no effect, setting to `true`
* when already `true` will not {@link ITimerHandler.refresh | refresh}() the timer.
* And setting to 'false` will {@link ITimerHandler.cancel | cancel}() the timer.
* @since 0.8.1
* @example
* ```ts
* let theTimer = createTimeout(...);
*
* // Check if enabled
* theTimer.enabled; // false
*
* // Start the timer
* theTimer.enabled = true; // Same as calling refresh()
* theTimer.enabled; //true
*
* // Has no effect as it's already running
* theTimer.enabled = true;
*
* // Will refresh / restart the time
* theTimer.refresh()
*
* let theTimer = scheduleTimeout(...);
*
* // Check if enabled
* theTimer.enabled; // true
* ```
*/
enabled: boolean;
}

/**
* @ignore
* @internal
*/
export interface _TimerHandler {
/**
* The public handler to return to the caller
*/
h: ITimerHandler,

/**
* The callback function that should be called when the timer operation
* has completed and will not automatically rescheduled
* @returns
*/
dn: () => void
}

/**
Expand All @@ -101,49 +157,70 @@ export interface ITimerHandler {
* it directly used / returned by the pulic functions used to create timers (idle, interval and timeout)
* @param startTimer - Should the timer be started as part of creating the handler
* @param refreshFn - The function used to create/start or refresh the timer
* @param cancelFn - The function used to cancel the timer
* @param cancelFn - The function used to cancel the timer.
* @returns The new ITimerHandler instance
*/
export function _createTimerHandler<T>(startTimer: boolean, refreshFn: (timerId: T) => T, cancelFn: (timerId: T) => void): ITimerHandler {
export function _createTimerHandler<T>(startTimer: boolean, refreshFn: (timerId: T) => T, cancelFn: (timerId: T) => void): _TimerHandler {
let ref = true;
let timerId: T = startTimer ? refreshFn(null) : null;
let theTimerHandler: ITimerHandler;

function _unref() {
const _unref = () => {
ref = false;
timerId && timerId["unref"] && timerId["unref"]();
return timer;
}
timerId && timerId[UNREF] && timerId[UNREF]();
return theTimerHandler;
};

function _ref() {
const _ref = () => {
ref = true;
timerId && timerId["ref"] && timerId["ref"]();
return timer;
}
timerId && timerId[REF] && timerId[REF]();
return theTimerHandler;
};

function _hasRef() {
if (timerId && timerId["hasRef"]) {
return timerId["hasRef"]();
const _hasRef = () => {
if (timerId && timerId[HAS_REF]) {
return timerId[HAS_REF]();
}
return ref;
};

const _refresh = () => {
timerId = refreshFn(timerId);
if (!ref) {
_unref();
}

return theTimerHandler;
};

const _cancel = () => {
timerId && cancelFn(timerId);
timerId = null;
};

const _setEnabled = (value: boolean) => {
!value && timerId && _cancel();
value && !timerId && _refresh();
}

let timer: ITimerHandler = {
cancel: function() {
timerId && cancelFn(timerId);
timerId = null;
},
refresh: function() {
timerId = refreshFn(timerId);
if (!ref) {
_unref();
}

return timer;
},
hasRef: _hasRef,
ref: _ref,
unref: _unref
theTimerHandler = {
cancel: _cancel,
refresh: _refresh,
[HAS_REF]: _hasRef,
[REF]: _ref,
[UNREF]: _unref,
[ENABLED]: false
};

return timer;
objDefineProp(theTimerHandler, ENABLED, {
get: () => !!timerId,
set: _setEnabled
});

return {
h: theTimerHandler,
dn: () => {
timerId = null;
}
};
}
15 changes: 11 additions & 4 deletions lib/src/timer/idle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,11 @@ export function setDefaultMaxExecutionTime(maxTime: number) {
* // Instead of calling cancelIdleCallback() with the returned value from requestIdleCallback() the returned
* // handler instance can be used instead to cancel the idle timer
* theIdleTimer.cancel();
*
* theIdleTimer.enabled; // false
*
* // You can start the timer via enabled
* theIdleTimer.enabled = true;
*
* // You can also "restart" the timer, whether it has previously triggered not not via the `refresh()`
* theIdleTimer.refresh();
* ```
Expand All @@ -130,14 +134,17 @@ export function scheduleIdleCallback(callback: IdleRequestCallback, options?: Id
}

if (hasIdleCallback()) {
return _createTimerHandler(true, function (idleId: number) {
let handler = _createTimerHandler(true, (idleId: number) => {
idleId && cancelIdleCallback(idleId);
return requestIdleCallback((deadline: IdleDeadline) => {
handler.dn();
callback(deadline || _createDeadline(false));
}, options);
}, function(idleId: number) {
}, (idleId: number) => {
cancelIdleCallback(idleId);
})
});

return handler.h;
}

let timeout = (options || {}).timeout;
Expand Down
12 changes: 9 additions & 3 deletions lib/src/timer/interval.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,12 @@ import { ITimerHandler, _createTimerHandler } from "./handler";
* // Instead of calling clearInterval() with the returned value from setInterval() the returned
* // handler instance can be used instead to cancel the timer
* theIntervalTimer.cancel();
* theIntervalTimer.enabled; // false
*
* // You can start the timer via enabled
* theIntervalTimer.enabled = true;
*
* // You can also "restart" the timer, whether it has previously triggered not not via the `refresh()`
* // Or you can also "restart" the timer, whether it has previously triggered not not via the `refresh()`
* theIntervalTimer.refresh();
* ```
*/
Expand All @@ -42,10 +46,12 @@ export function scheduleInterval<A extends any[]>(callback: (...args: A) => void
let self = this;
let theArguments = _extractArgs(arguments, 0);

return _createTimerHandler(true, function (intervalId: any) {
let handler = _createTimerHandler(true, (intervalId: any) => {
intervalId && clearInterval(intervalId);
return setInterval.apply(self, theArguments);
}, function (intervalId: any) {
}, (intervalId: any) => {
clearInterval(intervalId);
});

return handler.h;
}
33 changes: 31 additions & 2 deletions lib/src/timer/timeout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,13 @@ function _createTimeoutWith(self: any, startTimer: boolean, overrideFn: TimeoutO
let setFn: TimeoutOverrideFn = (len > 0 ? overrideFn[0] : (!isArr ? overrideFn : UNDEF_VALUE)) || setTimeout;
let clearFn: ClearTimeoutOverrideFn = (len > 1 ? overrideFn[1] : UNDEF_VALUE) || clearTimeout;

return _createTimerHandler(startTimer, function (timerId?: any) {
let timerFn = theArgs[0];
theArgs[0] = function () {
handler.dn();
timerFn.apply(self, arguments);
};

let handler = _createTimerHandler(startTimer, (timerId?: any) => {
if (timerId) {
if (timerId.refresh) {
timerId.refresh();
Expand All @@ -31,6 +37,8 @@ function _createTimeoutWith(self: any, startTimer: boolean, overrideFn: TimeoutO
}, function (timerId: any) {
clearFn.call(self, timerId);
});

return handler.h;
}

/**
Expand Down Expand Up @@ -92,7 +100,11 @@ export type TimeoutOverrideFuncs = [ TimeoutOverrideFn | null, ClearTimeoutOverr
* // Instead of calling clearTimeout() with the returned value from setTimeout() the returned
* // handler instance can be used instead to cancel the timer
* theTimeout.cancel();
*
* theTimeout.enabled; // false
*
* // You can start the timer via enabled
* theTimeout.enabled = true;
*
* // You can also "restart" the timer, whether it has previously triggered not not via the `refresh()`
* theTimeout.refresh();
* ```
Expand Down Expand Up @@ -141,6 +153,10 @@ export function scheduleTimeout<A extends any[]>(callback: (...args: A) => void,
* // Instead of calling clearTimeout() with the returned value from setTimeout() the returned
* // handler instance can be used instead to cancel the timer
* theTimeout.cancel();
* theTimeout.enabled; // false
*
* // You can start the timer via enabled
* theTimeout.enabled = true;
*
* // You can also "restart" the timer, whether it has previously triggered not not via the `refresh()`
* theTimeout.refresh();
Expand Down Expand Up @@ -170,6 +186,10 @@ export function scheduleTimeout<A extends any[]>(callback: (...args: A) => void,
* // Instead of calling clearTimeout() with the returned value from setTimeout() the returned
* // handler instance can be used instead to cancel the timer, internally this will call the newClearTimeoutFn
* theTimeout.cancel();
* theTimeout.enabled; // false
*
* // You can start the timer via enabled
* theTimeout.enabled = true;
*
* // You can also "restart" the timer, whether it has previously triggered not not via the `refresh()`
* theTimeout.refresh();
Expand Down Expand Up @@ -207,6 +227,9 @@ export function scheduleTimeoutWith<A extends any[]>(overrideFn: TimeoutOverride
*
* // As the timer is not started you will need to call "refresh" to start the timer
* theTimeout.refresh();
*
* // or set enabled to true
* theTimeout.enabled = true;
* ```
*/
export function createTimeout<A extends any[]>(callback: (...args: A) => void, timeout: number, ...args: A): ITimerHandler;
Expand Down Expand Up @@ -252,6 +275,9 @@ export function createTimeout<A extends any[]>(callback: (...args: A) => void, t
*
* // As the timer is not started you will need to call "refresh" to start the timer
* theTimeout.refresh();
*
* // or set enabled to true
* theTimeout.enabled = true;
* ```
* @example
* ```ts
Expand All @@ -277,6 +303,9 @@ export function createTimeout<A extends any[]>(callback: (...args: A) => void, t
*
* // As the timer is not started you will need to call "refresh" to start the timer
* theTimeout.refresh();
*
* // or set enabled to true
* theTimeout.enabled = true;
* ```
*/
export function createTimeoutWith<A extends any[]>(overrideFn: TimeoutOverrideFn | TimeoutOverrideFuncs, callback: (...args: A) => void, timeout: number, ...args: A): ITimerHandler;
Expand Down
Loading

0 comments on commit 330d852

Please sign in to comment.