@khanacademy/wonder-blocks-timing
Advanced tools
Comparing version 1.2.3 to 2.0.0
import _extends from '@babel/runtime/helpers/extends'; | ||
import { Component, forwardRef, createElement } from 'react'; | ||
const SchedulePolicy = { | ||
Immediately: "schedule-immediately", | ||
OnDemand: "schedule-on-demand" | ||
}; | ||
const ClearPolicy = { | ||
Resolve: "resolve-on-clear", | ||
Cancel: "cancel-on-clear" | ||
}; | ||
/** | ||
@@ -21,8 +30,9 @@ * Encapsulates everything associated with calling setTimeout/clearTimeout, and | ||
* @param {number} timeoutMs The timeout period. | ||
* @param {boolean} [autoSchedule] When true, the timer is set immediately on | ||
* instanstiation; otherwise, `set` must be called to set the timeout. | ||
* Defaults to `true`. | ||
* @param {SchedulePolicy} [schedulePolicy] When SchedulePolicy.Immediately, | ||
* the timer is set immediately on instantiation; otherwise, `set` must be | ||
* called to set the timeout. | ||
* Defaults to `SchedulePolicy.Immediately`. | ||
* @memberof Timeout | ||
*/ | ||
constructor(action, timeoutMs, autoSchedule) { | ||
constructor(action, timeoutMs, schedulePolicy = SchedulePolicy.Immediately) { | ||
if (typeof action !== "function") { | ||
@@ -39,3 +49,3 @@ throw new Error("Action must be a function"); | ||
if (autoSchedule || autoSchedule == null) { | ||
if (schedulePolicy === SchedulePolicy.Immediately) { | ||
this.set(); | ||
@@ -69,6 +79,6 @@ } | ||
if (this.isSet) { | ||
this.clear(false); | ||
this.clear(ClearPolicy.Cancel); | ||
} | ||
this._timeoutId = setTimeout(() => this.clear(true), this._timeoutMs); | ||
this._timeoutId = setTimeout(() => this.clear(ClearPolicy.Resolve), this._timeoutMs); | ||
} | ||
@@ -81,5 +91,6 @@ /** | ||
* | ||
* @param {boolean} [resolve] When true, if the timeout was set when called, | ||
* the timeout action is invoked after cancelling the timeout. Defaults to | ||
* false. | ||
* @param {ClearPolicy} [policy] When ClearPolicy.Resolve, if the request | ||
* was set when called, the request action is invoked after cancelling | ||
* the request; otherwise, the pending action is cancelled. | ||
* Defaults to `ClearPolicy.Cancel`. | ||
* | ||
@@ -91,3 +102,3 @@ * @returns {void} | ||
clear(resolve) { | ||
clear(policy = ClearPolicy.Cancel) { | ||
const timeoutId = this._timeoutId; | ||
@@ -102,3 +113,3 @@ this._timeoutId = null; | ||
if (resolve) { | ||
if (policy === ClearPolicy.Resolve) { | ||
this._action(); | ||
@@ -127,9 +138,9 @@ } | ||
* @param {number} intervalMs The interval period. | ||
* @param {boolean} [autoSchedule] When true, the interval is activated | ||
* immediately on instanstiation; otherwise, `set` must be called to | ||
* activate the interval. | ||
* Defaults to `true`. | ||
* @param {SchedulePolicy} [schedulePolicy] When SchedulePolicy.Immediately, | ||
* the interval is set immediately on instantiation; otherwise, `set` must be | ||
* called to set the interval. | ||
* Defaults to `SchedulePolicy.Immediately`. | ||
* @memberof Interval | ||
*/ | ||
constructor(action, intervalMs, autoSchedule) { | ||
constructor(action, intervalMs, schedulePolicy = SchedulePolicy.Immediately) { | ||
if (typeof action !== "function") { | ||
@@ -146,3 +157,3 @@ throw new Error("Action must be a function"); | ||
if (autoSchedule || autoSchedule == null) { | ||
if (schedulePolicy === SchedulePolicy.Immediately) { | ||
this.set(); | ||
@@ -174,3 +185,3 @@ } | ||
if (this.isSet) { | ||
this.clear(false); | ||
this.clear(ClearPolicy.Cancel); | ||
} | ||
@@ -186,5 +197,6 @@ | ||
* | ||
* @param {boolean} [resolve] When true, if the interval was active when | ||
* called, the interval action is invoked after cancellation. Defaults to | ||
* false. | ||
* @param {ClearPolicy} [policy] When ClearPolicy.Resolve, if the request | ||
* was set when called, the request action is invoked after cancelling | ||
* the request; otherwise, the pending action is cancelled. | ||
* Defaults to `ClearPolicy.Cancel`. | ||
* | ||
@@ -196,3 +208,3 @@ * @returns {void} | ||
clear(resolve) { | ||
clear(policy = ClearPolicy.Cancel) { | ||
const intervalId = this._intervalId; | ||
@@ -207,3 +219,3 @@ this._intervalId = null; | ||
if (resolve) { | ||
if (policy === ClearPolicy.Resolve) { | ||
this._action(); | ||
@@ -230,8 +242,9 @@ } | ||
* @param {DOMHighResTimeStamp => mixed} action The action to be invoked. | ||
* @param {boolean} [autoSchedule] When true, the request is made immediately on | ||
* instanstiation; otherwise, `set` must be called to make the request. | ||
* Defaults to `true`. | ||
* @param {SchedulePolicy} [schedulePolicy] When SchedulePolicy.Immediately, | ||
* the interval is set immediately on instantiation; otherwise, `set` must be | ||
* called to set the interval. | ||
* Defaults to `SchedulePolicy.Immediately`. | ||
* @memberof AnimationFrame | ||
*/ | ||
constructor(action, autoSchedule) { | ||
constructor(action, schedulePolicy = SchedulePolicy.Immediately) { | ||
if (typeof action !== "function") { | ||
@@ -243,3 +256,3 @@ throw new Error("Action must be a function"); | ||
if (autoSchedule || autoSchedule == null) { | ||
if (schedulePolicy === SchedulePolicy.Immediately) { | ||
this.set(); | ||
@@ -273,6 +286,6 @@ } | ||
if (this.isSet) { | ||
this.clear(false); | ||
this.clear(ClearPolicy.Cancel); | ||
} | ||
this._animationFrameId = requestAnimationFrame(time => this.clear(true, time)); | ||
this._animationFrameId = requestAnimationFrame(time => this.clear(ClearPolicy.Resolve, time)); | ||
} | ||
@@ -285,5 +298,9 @@ /** | ||
* | ||
* @param {boolean} [resolve] When true, if the request was pending when | ||
* called, the request action is invoked after cancelling the timeout. | ||
* Defaults to false. | ||
* @param {ClearPolicy} [policy] When ClearPolicy.Resolve, if the request | ||
* was set when called, the request action is invoked after cancelling | ||
* the request; otherwise, the pending action is cancelled. | ||
* Defaults to `ClearPolicy.Cancel`. | ||
* @param {DOMHighResTimeStamp} [time] Timestamp to pass to the action when | ||
* ClearPolicy.Resolve is specified. Ignored when ClearPolicy.Cancel is | ||
* specified. | ||
* | ||
@@ -295,3 +312,3 @@ * @returns {void} | ||
clear(resolve, time) { | ||
clear(policy = ClearPolicy.Cancel, time) { | ||
const animationFrameId = this._animationFrameId; | ||
@@ -306,3 +323,3 @@ this._animationFrameId = null; | ||
if (resolve) { | ||
if (policy === ClearPolicy.Resolve) { | ||
this._action(time || performance.now()); | ||
@@ -322,26 +339,39 @@ } | ||
constructor() { | ||
this._disabled = false; | ||
this._registeredActions = []; | ||
} | ||
timeout(action, period, autoSchedule, resolveOnClear) { | ||
const timeout = new Timeout(action, period, autoSchedule); | ||
timeout(action, period, options) { | ||
if (this._disabled) { | ||
return ActionScheduler.NoopAction; | ||
} | ||
this._registeredActions.push(() => timeout.clear(resolveOnClear)); | ||
const timeout = new Timeout(action, period, options == null ? void 0 : options.schedulePolicy); | ||
this._registeredActions.push(() => timeout.clear(options == null ? void 0 : options.clearPolicy)); | ||
return timeout; | ||
} | ||
interval(action, period, autoSchedule, resolveOnClear) { | ||
const interval = new Interval(action, period, autoSchedule); | ||
interval(action, period, options) { | ||
if (this._disabled) { | ||
return ActionScheduler.NoopAction; | ||
} | ||
this._registeredActions.push(() => interval.clear(resolveOnClear)); | ||
const interval = new Interval(action, period, options == null ? void 0 : options.schedulePolicy); | ||
this._registeredActions.push(() => interval.clear(options == null ? void 0 : options.clearPolicy)); | ||
return interval; | ||
} | ||
animationFrame(action, autoSchedule, resolveOnClear) { | ||
const animationFrame = new AnimationFrame(action, autoSchedule); | ||
animationFrame(action, options) { | ||
if (this._disabled) { | ||
return ActionScheduler.NoopAction; | ||
} | ||
this._registeredActions.push(() => animationFrame.clear(resolveOnClear)); | ||
const animationFrame = new AnimationFrame(action, options == null ? void 0 : options.schedulePolicy); | ||
this._registeredActions.push(() => animationFrame.clear(options == null ? void 0 : options.clearPolicy)); | ||
return animationFrame; | ||
@@ -355,5 +385,24 @@ } | ||
} | ||
/** | ||
* Prevents this scheduler from creating any additional actions. | ||
* This also clears any pending actions. | ||
*/ | ||
disable() { | ||
this._disabled = true; | ||
this.clearAll(); | ||
} | ||
} | ||
ActionScheduler.NoopAction = { | ||
set: () => {}, | ||
get isSet() { | ||
return false; | ||
}, | ||
clear: () => {} | ||
}; | ||
/** | ||
@@ -376,3 +425,3 @@ * A provider component that passes our action scheduling API to its children | ||
componentWillUnmount() { | ||
this._actionScheduler.clearAll(); | ||
this._actionScheduler.disable(); | ||
} | ||
@@ -405,2 +454,2 @@ | ||
export { withActionScheduler }; | ||
export { ClearPolicy, SchedulePolicy, withActionScheduler }; |
@@ -129,4 +129,15 @@ module.exports = | ||
// EXPORTS | ||
__webpack_require__.d(__webpack_exports__, "SchedulePolicy", function() { return /* reexport */ SchedulePolicy; }); | ||
__webpack_require__.d(__webpack_exports__, "ClearPolicy", function() { return /* reexport */ ClearPolicy; }); | ||
__webpack_require__.d(__webpack_exports__, "withActionScheduler", function() { return /* reexport */ withActionScheduler; }); | ||
// CONCATENATED MODULE: ./packages/wonder-blocks-timing/src/util/policies.js | ||
const SchedulePolicy = { | ||
Immediately: "schedule-immediately", | ||
OnDemand: "schedule-on-demand" | ||
}; | ||
const ClearPolicy = { | ||
Resolve: "resolve-on-clear", | ||
Cancel: "cancel-on-clear" | ||
}; | ||
// EXTERNAL MODULE: ./node_modules/@babel/runtime/helpers/extends.js | ||
@@ -140,2 +151,4 @@ var helpers_extends = __webpack_require__(1); | ||
// CONCATENATED MODULE: ./packages/wonder-blocks-timing/src/util/timeout.js | ||
/** | ||
@@ -150,3 +163,3 @@ * Encapsulates everything associated with calling setTimeout/clearTimeout, and | ||
*/ | ||
class Timeout { | ||
class timeout_Timeout { | ||
/** | ||
@@ -159,8 +172,9 @@ * Creates a timeout that will invoke the given action after | ||
* @param {number} timeoutMs The timeout period. | ||
* @param {boolean} [autoSchedule] When true, the timer is set immediately on | ||
* instanstiation; otherwise, `set` must be called to set the timeout. | ||
* Defaults to `true`. | ||
* @param {SchedulePolicy} [schedulePolicy] When SchedulePolicy.Immediately, | ||
* the timer is set immediately on instantiation; otherwise, `set` must be | ||
* called to set the timeout. | ||
* Defaults to `SchedulePolicy.Immediately`. | ||
* @memberof Timeout | ||
*/ | ||
constructor(action, timeoutMs, autoSchedule) { | ||
constructor(action, timeoutMs, schedulePolicy = SchedulePolicy.Immediately) { | ||
if (typeof action !== "function") { | ||
@@ -177,3 +191,3 @@ throw new Error("Action must be a function"); | ||
if (autoSchedule || autoSchedule == null) { | ||
if (schedulePolicy === SchedulePolicy.Immediately) { | ||
this.set(); | ||
@@ -207,6 +221,6 @@ } | ||
if (this.isSet) { | ||
this.clear(false); | ||
this.clear(ClearPolicy.Cancel); | ||
} | ||
this._timeoutId = setTimeout(() => this.clear(true), this._timeoutMs); | ||
this._timeoutId = setTimeout(() => this.clear(ClearPolicy.Resolve), this._timeoutMs); | ||
} | ||
@@ -219,5 +233,6 @@ /** | ||
* | ||
* @param {boolean} [resolve] When true, if the timeout was set when called, | ||
* the timeout action is invoked after cancelling the timeout. Defaults to | ||
* false. | ||
* @param {ClearPolicy} [policy] When ClearPolicy.Resolve, if the request | ||
* was set when called, the request action is invoked after cancelling | ||
* the request; otherwise, the pending action is cancelled. | ||
* Defaults to `ClearPolicy.Cancel`. | ||
* | ||
@@ -229,3 +244,3 @@ * @returns {void} | ||
clear(resolve) { | ||
clear(policy = ClearPolicy.Cancel) { | ||
const timeoutId = this._timeoutId; | ||
@@ -240,3 +255,3 @@ this._timeoutId = null; | ||
if (resolve) { | ||
if (policy === ClearPolicy.Resolve) { | ||
this._action(); | ||
@@ -248,2 +263,4 @@ } | ||
// CONCATENATED MODULE: ./packages/wonder-blocks-timing/src/util/interval.js | ||
/** | ||
@@ -258,3 +275,3 @@ * Encapsulates everything associated with calling setInterval/clearInterval, | ||
*/ | ||
class Interval { | ||
class interval_Interval { | ||
/** | ||
@@ -267,9 +284,9 @@ * Creates an interval that will invoke the given action after | ||
* @param {number} intervalMs The interval period. | ||
* @param {boolean} [autoSchedule] When true, the interval is activated | ||
* immediately on instanstiation; otherwise, `set` must be called to | ||
* activate the interval. | ||
* Defaults to `true`. | ||
* @param {SchedulePolicy} [schedulePolicy] When SchedulePolicy.Immediately, | ||
* the interval is set immediately on instantiation; otherwise, `set` must be | ||
* called to set the interval. | ||
* Defaults to `SchedulePolicy.Immediately`. | ||
* @memberof Interval | ||
*/ | ||
constructor(action, intervalMs, autoSchedule) { | ||
constructor(action, intervalMs, schedulePolicy = SchedulePolicy.Immediately) { | ||
if (typeof action !== "function") { | ||
@@ -286,3 +303,3 @@ throw new Error("Action must be a function"); | ||
if (autoSchedule || autoSchedule == null) { | ||
if (schedulePolicy === SchedulePolicy.Immediately) { | ||
this.set(); | ||
@@ -314,3 +331,3 @@ } | ||
if (this.isSet) { | ||
this.clear(false); | ||
this.clear(ClearPolicy.Cancel); | ||
} | ||
@@ -326,5 +343,6 @@ | ||
* | ||
* @param {boolean} [resolve] When true, if the interval was active when | ||
* called, the interval action is invoked after cancellation. Defaults to | ||
* false. | ||
* @param {ClearPolicy} [policy] When ClearPolicy.Resolve, if the request | ||
* was set when called, the request action is invoked after cancelling | ||
* the request; otherwise, the pending action is cancelled. | ||
* Defaults to `ClearPolicy.Cancel`. | ||
* | ||
@@ -336,3 +354,3 @@ * @returns {void} | ||
clear(resolve) { | ||
clear(policy = ClearPolicy.Cancel) { | ||
const intervalId = this._intervalId; | ||
@@ -347,3 +365,3 @@ this._intervalId = null; | ||
if (resolve) { | ||
if (policy === ClearPolicy.Resolve) { | ||
this._action(); | ||
@@ -355,2 +373,4 @@ } | ||
// CONCATENATED MODULE: ./packages/wonder-blocks-timing/src/util/animation-frame.js | ||
/** | ||
@@ -365,3 +385,3 @@ * Encapsulates everything associated with calling requestAnimationFrame/ | ||
*/ | ||
class AnimationFrame { | ||
class animation_frame_AnimationFrame { | ||
/** | ||
@@ -372,8 +392,9 @@ * Creates an animation frame request that will invoke the given action. | ||
* @param {DOMHighResTimeStamp => mixed} action The action to be invoked. | ||
* @param {boolean} [autoSchedule] When true, the request is made immediately on | ||
* instanstiation; otherwise, `set` must be called to make the request. | ||
* Defaults to `true`. | ||
* @param {SchedulePolicy} [schedulePolicy] When SchedulePolicy.Immediately, | ||
* the interval is set immediately on instantiation; otherwise, `set` must be | ||
* called to set the interval. | ||
* Defaults to `SchedulePolicy.Immediately`. | ||
* @memberof AnimationFrame | ||
*/ | ||
constructor(action, autoSchedule) { | ||
constructor(action, schedulePolicy = SchedulePolicy.Immediately) { | ||
if (typeof action !== "function") { | ||
@@ -385,3 +406,3 @@ throw new Error("Action must be a function"); | ||
if (autoSchedule || autoSchedule == null) { | ||
if (schedulePolicy === SchedulePolicy.Immediately) { | ||
this.set(); | ||
@@ -415,6 +436,6 @@ } | ||
if (this.isSet) { | ||
this.clear(false); | ||
this.clear(ClearPolicy.Cancel); | ||
} | ||
this._animationFrameId = requestAnimationFrame(time => this.clear(true, time)); | ||
this._animationFrameId = requestAnimationFrame(time => this.clear(ClearPolicy.Resolve, time)); | ||
} | ||
@@ -427,5 +448,9 @@ /** | ||
* | ||
* @param {boolean} [resolve] When true, if the request was pending when | ||
* called, the request action is invoked after cancelling the timeout. | ||
* Defaults to false. | ||
* @param {ClearPolicy} [policy] When ClearPolicy.Resolve, if the request | ||
* was set when called, the request action is invoked after cancelling | ||
* the request; otherwise, the pending action is cancelled. | ||
* Defaults to `ClearPolicy.Cancel`. | ||
* @param {DOMHighResTimeStamp} [time] Timestamp to pass to the action when | ||
* ClearPolicy.Resolve is specified. Ignored when ClearPolicy.Cancel is | ||
* specified. | ||
* | ||
@@ -437,3 +462,3 @@ * @returns {void} | ||
clear(resolve, time) { | ||
clear(policy = ClearPolicy.Cancel, time) { | ||
const animationFrameId = this._animationFrameId; | ||
@@ -448,3 +473,3 @@ this._animationFrameId = null; | ||
if (resolve) { | ||
if (policy === ClearPolicy.Resolve) { | ||
this._action(time || performance.now()); | ||
@@ -468,26 +493,39 @@ } | ||
constructor() { | ||
this._disabled = false; | ||
this._registeredActions = []; | ||
} | ||
timeout(action, period, autoSchedule, resolveOnClear) { | ||
const timeout = new Timeout(action, period, autoSchedule); | ||
timeout(action, period, options) { | ||
if (this._disabled) { | ||
return action_scheduler_ActionScheduler.NoopAction; | ||
} | ||
this._registeredActions.push(() => timeout.clear(resolveOnClear)); | ||
const timeout = new timeout_Timeout(action, period, options == null ? void 0 : options.schedulePolicy); | ||
this._registeredActions.push(() => timeout.clear(options == null ? void 0 : options.clearPolicy)); | ||
return timeout; | ||
} | ||
interval(action, period, autoSchedule, resolveOnClear) { | ||
const interval = new Interval(action, period, autoSchedule); | ||
interval(action, period, options) { | ||
if (this._disabled) { | ||
return action_scheduler_ActionScheduler.NoopAction; | ||
} | ||
this._registeredActions.push(() => interval.clear(resolveOnClear)); | ||
const interval = new interval_Interval(action, period, options == null ? void 0 : options.schedulePolicy); | ||
this._registeredActions.push(() => interval.clear(options == null ? void 0 : options.clearPolicy)); | ||
return interval; | ||
} | ||
animationFrame(action, autoSchedule, resolveOnClear) { | ||
const animationFrame = new AnimationFrame(action, autoSchedule); | ||
animationFrame(action, options) { | ||
if (this._disabled) { | ||
return action_scheduler_ActionScheduler.NoopAction; | ||
} | ||
this._registeredActions.push(() => animationFrame.clear(resolveOnClear)); | ||
const animationFrame = new animation_frame_AnimationFrame(action, options == null ? void 0 : options.schedulePolicy); | ||
this._registeredActions.push(() => animationFrame.clear(options == null ? void 0 : options.clearPolicy)); | ||
return animationFrame; | ||
@@ -501,4 +539,23 @@ } | ||
} | ||
/** | ||
* Prevents this scheduler from creating any additional actions. | ||
* This also clears any pending actions. | ||
*/ | ||
disable() { | ||
this._disabled = true; | ||
this.clearAll(); | ||
} | ||
} | ||
action_scheduler_ActionScheduler.NoopAction = { | ||
set: () => {}, | ||
get isSet() { | ||
return false; | ||
}, | ||
clear: () => {} | ||
}; | ||
// CONCATENATED MODULE: ./packages/wonder-blocks-timing/src/components/action-scheduler-provider.js | ||
@@ -525,3 +582,3 @@ | ||
componentWillUnmount() { | ||
this._actionScheduler.clearAll(); | ||
this._actionScheduler.disable(); | ||
} | ||
@@ -560,3 +617,4 @@ | ||
/***/ }) | ||
/******/ ]); |
{ | ||
"name": "@khanacademy/wonder-blocks-timing", | ||
"private": false, | ||
"version": "1.2.3", | ||
"version": "2.0.0", | ||
"design": "v1", | ||
@@ -24,3 +24,3 @@ "publishConfig": { | ||
"license": "MIT", | ||
"gitHead": "8022bb419eed74be37f71f71c7621854794a731c" | ||
"gitHead": "ddf9842bf1e9502a3287be19fe01544c3823d116" | ||
} |
@@ -24,3 +24,3 @@ // @flow | ||
it("should call clearAll on the action scheduler at unmount", () => { | ||
it("should call disable on the action scheduler at unmount", () => { | ||
// Arrange | ||
@@ -36,5 +36,5 @@ const childrenMock = jest.fn().mockReturnValueOnce(null); | ||
// Assert | ||
// $FlowIgnore[method-unbinding] | ||
expect(childrenMock.mock.calls[0][0].clearAll).toHaveBeenCalledTimes(1); | ||
// $FlowIgnore[prop-missing] | ||
expect(childrenMock.mock.calls[0][0].disable).toHaveBeenCalledTimes(1); | ||
}); | ||
}); |
@@ -27,6 +27,6 @@ // @flow | ||
componentWillUnmount() { | ||
this._actionScheduler.clearAll(); | ||
this._actionScheduler.disable(); | ||
} | ||
_actionScheduler: IScheduleActions = new ActionScheduler(); | ||
_actionScheduler: ActionScheduler = new ActionScheduler(); | ||
@@ -33,0 +33,0 @@ render(): React.Node { |
@@ -24,8 +24,12 @@ // @flow | ||
export default function withActionScheduler< | ||
Config: {...}, | ||
Component: React.ComponentType<WithActionScheduler<Config>>, | ||
-Config: WithActionSchedulerProps, | ||
+Instance, | ||
Component: React.AbstractComponent<WithActionScheduler<Config>, Instance>, | ||
>( | ||
WrappedComponent: Component, | ||
): React.ComponentType<WithoutActionScheduler<React.ElementConfig<Component>>> { | ||
return React.forwardRef((props, ref) => ( | ||
): React.AbstractComponent< | ||
WithoutActionScheduler<React.ElementConfig<Component>>, | ||
Instance, | ||
> { | ||
return React.forwardRef<_, Instance>((props, ref) => ( | ||
<ActionSchedulerProvider> | ||
@@ -32,0 +36,0 @@ {(schedule: IScheduleActions) => ( |
@@ -22,2 +22,3 @@ // @flow | ||
export {SchedulePolicy, ClearPolicy} from "./util/policies.js"; | ||
export {default as withActionScheduler} from "./components/with-action-scheduler.js"; |
@@ -6,2 +6,3 @@ // @flow | ||
import AnimationFrame from "../animation-frame.js"; | ||
import {SchedulePolicy, ClearPolicy} from "../policies.js"; | ||
@@ -42,51 +43,50 @@ jest.mock("../timeout.js"); | ||
it("should pass arguments to Timeout", () => { | ||
it("should pass schedule policy to Timeout", () => { | ||
// Arrange | ||
const actionScheduler = new ActionScheduler(); | ||
const action = jest.fn(); | ||
const options = { | ||
schedulePolicy: SchedulePolicy.Immediately, | ||
}; | ||
// Act | ||
actionScheduler.timeout(action, 42, true); | ||
actionScheduler.timeout(action, 42, options); | ||
// Assert | ||
expect(Timeout).toHaveBeenCalledWith(action, 42, true); | ||
expect(Timeout).toHaveBeenCalledWith( | ||
action, | ||
42, | ||
SchedulePolicy.Immediately, | ||
); | ||
}); | ||
describe("clearOnResolve", () => { | ||
it("when true, should call timeout.clear(true) on clearAll", () => { | ||
// Arrange | ||
const actionScheduler = new ActionScheduler(); | ||
const action = jest.fn(); | ||
const testTimeout = actionScheduler.timeout( | ||
action, | ||
42, | ||
false, | ||
true, | ||
); | ||
it("should pass clear policy to timeout.clear on clearAll", () => { | ||
// Arrange | ||
const actionScheduler = new ActionScheduler(); | ||
const action = jest.fn(); | ||
const options = { | ||
clearPolicy: ClearPolicy.Resolve, | ||
}; | ||
const testTimeout = actionScheduler.timeout(action, 42, options); | ||
// Act | ||
actionScheduler.clearAll(); | ||
// Act | ||
actionScheduler.clearAll(); | ||
// Assert | ||
// $FlowIgnore[method-unbinding] | ||
expect(testTimeout.clear).toHaveBeenCalledWith(true); | ||
}); | ||
// Assert | ||
// $FlowIgnore[method-unbinding] | ||
expect(testTimeout.clear).toHaveBeenCalledWith(ClearPolicy.Resolve); | ||
}); | ||
it("when falsy, should call timeout.clear() on clearAll", () => { | ||
describe("when scheduler is disabled", () => { | ||
it("should return a noop timeout", () => { | ||
// Arrange | ||
const actionScheduler = new ActionScheduler(); | ||
const action = jest.fn(); | ||
const testTimeout = actionScheduler.timeout( | ||
action, | ||
42, | ||
false, | ||
false, | ||
); | ||
// Act | ||
actionScheduler.clearAll(); | ||
actionScheduler.disable(); | ||
const result = actionScheduler.timeout(action, 42); | ||
// Assert | ||
// $FlowIgnore[method-unbinding] | ||
expect(testTimeout.clear).toHaveBeenCalledWith(false); | ||
expect(result).toBe(ActionScheduler.NoopAction); | ||
}); | ||
@@ -109,51 +109,52 @@ }); | ||
it("should pass arguments to Interval", () => { | ||
it("should pass schedule policy to Interval", () => { | ||
// Arrange | ||
const actionScheduler = new ActionScheduler(); | ||
const action = jest.fn(); | ||
const options = { | ||
schedulePolicy: SchedulePolicy.Immediately, | ||
}; | ||
// Act | ||
actionScheduler.interval(action, 42, true); | ||
actionScheduler.interval(action, 42, options); | ||
// Assert | ||
expect(Interval).toHaveBeenCalledWith(action, 42, true); | ||
expect(Interval).toHaveBeenCalledWith( | ||
action, | ||
42, | ||
SchedulePolicy.Immediately, | ||
); | ||
}); | ||
describe("clearOnResolve", () => { | ||
it("when true, should call interval.clear(true) on clearAll", () => { | ||
// Arrange | ||
const actionScheduler = new ActionScheduler(); | ||
const action = jest.fn(); | ||
const testInterval = actionScheduler.interval( | ||
action, | ||
42, | ||
false, | ||
true, | ||
); | ||
it("should pass clear policy to interval.clear on clearAll", () => { | ||
// Arrange | ||
const actionScheduler = new ActionScheduler(); | ||
const action = jest.fn(); | ||
const options = { | ||
clearPolicy: ClearPolicy.Resolve, | ||
}; | ||
const testInterval = actionScheduler.interval(action, 42, options); | ||
// Act | ||
actionScheduler.clearAll(); | ||
// Act | ||
actionScheduler.clearAll(); | ||
// Assert | ||
// $FlowIgnore[method-unbinding] | ||
expect(testInterval.clear).toHaveBeenCalledWith(true); | ||
}); | ||
// Assert | ||
// $FlowIgnore[method-unbinding] | ||
expect(testInterval.clear).toHaveBeenCalledWith( | ||
ClearPolicy.Resolve, | ||
); | ||
}); | ||
it("when falsy, should call interval.clear() on clearAll", () => { | ||
describe("when scheduler is disabled", () => { | ||
it("should return a noop interval", () => { | ||
// Arrange | ||
const actionScheduler = new ActionScheduler(); | ||
const action = jest.fn(); | ||
const testInterval = actionScheduler.interval( | ||
action, | ||
42, | ||
false, | ||
false, | ||
); | ||
// Act | ||
actionScheduler.clearAll(); | ||
actionScheduler.disable(); | ||
const result = actionScheduler.interval(action, 42); | ||
// Assert | ||
// $FlowIgnore[method-unbinding] | ||
expect(testInterval.clear).toHaveBeenCalledWith(false); | ||
expect(result).toBe(ActionScheduler.NoopAction); | ||
}); | ||
@@ -176,49 +177,49 @@ }); | ||
it("should pass arguments to AnimationFrame", () => { | ||
it("should pass schedule policy to AnimationFrame", () => { | ||
// Arrange | ||
const actionScheduler = new ActionScheduler(); | ||
const action = jest.fn(); | ||
const options = { | ||
schedulePolicy: SchedulePolicy.Immediately, | ||
}; | ||
// Act | ||
actionScheduler.animationFrame(action, true); | ||
actionScheduler.animationFrame(action, options); | ||
// Assert | ||
expect(AnimationFrame).toHaveBeenCalledWith(action, true); | ||
expect(AnimationFrame).toHaveBeenCalledWith( | ||
action, | ||
SchedulePolicy.Immediately, | ||
); | ||
}); | ||
describe("clearOnResolve", () => { | ||
it("when true, should call animationFrame.clear(true) on clearAll", () => { | ||
// Arrange | ||
const actionScheduler = new ActionScheduler(); | ||
const action = jest.fn(); | ||
const testFrame = actionScheduler.animationFrame( | ||
action, | ||
false, | ||
true, | ||
); | ||
it("should pass clear policy to animationFrame.clear on clearAll", () => { | ||
// Arrange | ||
const actionScheduler = new ActionScheduler(); | ||
const action = jest.fn(); | ||
const options = { | ||
clearPolicy: ClearPolicy.Resolve, | ||
}; | ||
const testFrame = actionScheduler.animationFrame(action, options); | ||
// Act | ||
actionScheduler.clearAll(); | ||
// Act | ||
actionScheduler.clearAll(); | ||
// Assert | ||
// $FlowIgnore[method-unbinding] | ||
expect(testFrame.clear).toHaveBeenCalledWith(true); | ||
}); | ||
// Assert | ||
// $FlowIgnore[method-unbinding] | ||
expect(testFrame.clear).toHaveBeenCalledWith(ClearPolicy.Resolve); | ||
}); | ||
it("when falsy, should call animationFrame.clear() on clearAll", () => { | ||
describe("when scheduler is disabled", () => { | ||
it("should return a noop interval", () => { | ||
// Arrange | ||
const actionScheduler = new ActionScheduler(); | ||
const action = jest.fn(); | ||
const testFrame = actionScheduler.animationFrame( | ||
action, | ||
false, | ||
false, | ||
); | ||
// Act | ||
actionScheduler.clearAll(); | ||
actionScheduler.disable(); | ||
const result = actionScheduler.animationFrame(action); | ||
// Assert | ||
// $FlowIgnore[method-unbinding] | ||
expect(testFrame.clear).toHaveBeenCalledWith(false); | ||
expect(result).toBe(ActionScheduler.NoopAction); | ||
}); | ||
@@ -270,2 +271,16 @@ }); | ||
}); | ||
describe("#disable", () => { | ||
it("should clear all scheduled actions", () => { | ||
// Arrange | ||
const actionScheduler = new ActionScheduler(); | ||
const clearAllSpy = jest.spyOn(actionScheduler, "clearAll"); | ||
// Act | ||
actionScheduler.disable(); | ||
// Assert | ||
expect(clearAllSpy).toHaveBeenCalledTimes(1); | ||
}); | ||
}); | ||
}); |
// @flow | ||
import AnimationFrame from "../animation-frame.js"; | ||
import {SchedulePolicy, ClearPolicy} from "../policies.js"; | ||
@@ -48,3 +49,3 @@ describe("AnimationFrame", () => { | ||
it("requests an animation frame when autoSchedule is true", () => { | ||
it("requests an animation frame when schedule policy is SchedulePolicy.Immediately", () => { | ||
// Arrange | ||
@@ -54,3 +55,3 @@ | ||
// eslint-disable-next-line no-new | ||
new AnimationFrame(() => {}, true); | ||
new AnimationFrame(() => {}, SchedulePolicy.Immediately); | ||
@@ -65,3 +66,4 @@ // Assert | ||
// Arrange | ||
const animationFrame = new AnimationFrame(() => {}, false); | ||
const animationFrame = new AnimationFrame(() => {}, | ||
SchedulePolicy.OnDemand); | ||
@@ -150,3 +152,6 @@ // Act | ||
const action = jest.fn(); | ||
const animationFrame = new AnimationFrame(action, false); | ||
const animationFrame = new AnimationFrame( | ||
action, | ||
SchedulePolicy.OnDemand, | ||
); | ||
animationFrame.set(); | ||
@@ -178,3 +183,3 @@ jest.runOnlyPendingTimers(); | ||
it("should invoke the action if resolve is true", () => { | ||
it("should invoke the action if clear policy is ClearPolicy.Resolve", () => { | ||
// Arrange | ||
@@ -187,3 +192,3 @@ jest.spyOn(performance, "now").mockReturnValue(42); | ||
// Act | ||
animationFrame.clear(true); | ||
animationFrame.clear(ClearPolicy.Resolve); | ||
jest.runOnlyPendingTimers(); | ||
@@ -196,9 +201,12 @@ | ||
it("should not invoke the action if resolve is false", () => { | ||
it("should not invoke the action if clear policy is ClearPolicy.Cancel", () => { | ||
// Arrange | ||
const action = jest.fn(); | ||
const animationFrame = new AnimationFrame(action, true); | ||
const animationFrame = new AnimationFrame( | ||
action, | ||
SchedulePolicy.Immediately, | ||
); | ||
// Act | ||
animationFrame.clear(false); | ||
animationFrame.clear(ClearPolicy.Cancel); | ||
jest.runOnlyPendingTimers(); | ||
@@ -210,9 +218,12 @@ | ||
it("should not invoke the action if timeout is not pending", () => { | ||
it("should not invoke the action if timeout is not pending and clear policy is ClearPolicy.Resolve", () => { | ||
// Arrange | ||
const action = jest.fn(); | ||
const animationFrame = new AnimationFrame(action, false); | ||
const animationFrame = new AnimationFrame( | ||
action, | ||
SchedulePolicy.OnDemand, | ||
); | ||
// Act | ||
animationFrame.clear(true); | ||
animationFrame.clear(ClearPolicy.Resolve); | ||
jest.runOnlyPendingTimers(); | ||
@@ -219,0 +230,0 @@ |
// @flow | ||
import Interval from "../interval.js"; | ||
import {SchedulePolicy, ClearPolicy} from "../policies.js"; | ||
@@ -44,3 +45,3 @@ describe("Interval", () => { | ||
it("sets an interval when autoSchedule is true", () => { | ||
it("sets an interval when schedule policy is SchedulePolicy.Immediately", () => { | ||
// Arrange | ||
@@ -50,3 +51,3 @@ | ||
// eslint-disable-next-line no-new | ||
new Interval(() => {}, 1000, true); | ||
new Interval(() => {}, 1000, SchedulePolicy.Immediately); | ||
@@ -61,3 +62,7 @@ // Assert | ||
// Arrange | ||
const interval = new Interval(() => {}, 1000, false); | ||
const interval = new Interval( | ||
() => {}, | ||
1000, | ||
SchedulePolicy.OnDemand, | ||
); | ||
@@ -172,3 +177,3 @@ // Act | ||
it("should invoke the action if resolve is true", () => { | ||
it("should invoke the action if clear policy is ClearPolicy.Resolve", () => { | ||
// Arrange | ||
@@ -180,3 +185,3 @@ const action = jest.fn(); | ||
// Act | ||
interval.clear(true); | ||
interval.clear(ClearPolicy.Resolve); | ||
jest.runTimersToTime(501); | ||
@@ -188,9 +193,13 @@ | ||
it("should not invoke the action if resolve is false", () => { | ||
it("should not invoke the action if clear policy is ClearPolicy.Cancel", () => { | ||
// Arrange | ||
const action = jest.fn(); | ||
const interval = new Interval(action, 500, true); | ||
const interval = new Interval( | ||
action, | ||
500, | ||
SchedulePolicy.Immediately, | ||
); | ||
// Act | ||
interval.clear(false); | ||
interval.clear(ClearPolicy.Cancel); | ||
jest.runTimersToTime(501); | ||
@@ -202,9 +211,9 @@ | ||
it("should not invoke the action if interval is inactive", () => { | ||
it("should not invoke the action if interval is inactive and clear policy is ClearPolicy.Resolve", () => { | ||
// Arrange | ||
const action = jest.fn(); | ||
const interval = new Interval(action, 500, false); | ||
const interval = new Interval(action, 500, SchedulePolicy.OnDemand); | ||
// Act | ||
interval.clear(true); | ||
interval.clear(ClearPolicy.Resolve); | ||
jest.runTimersToTime(501); | ||
@@ -211,0 +220,0 @@ |
// @flow | ||
import Timeout from "../timeout.js"; | ||
import {SchedulePolicy, ClearPolicy} from "../policies.js"; | ||
@@ -44,3 +45,3 @@ describe("Timeout", () => { | ||
it("sets a timeout when autoSchedule is true", () => { | ||
it("sets a timeout when schedule policy is SchedulePolicy.Immediately", () => { | ||
// Arrange | ||
@@ -50,3 +51,3 @@ | ||
// eslint-disable-next-line no-new | ||
new Timeout(() => {}, 0, true); | ||
new Timeout(() => {}, 0, SchedulePolicy.Immediately); | ||
@@ -61,3 +62,3 @@ // Assert | ||
// Arrange | ||
const timeout = new Timeout(() => {}, 0, false); | ||
const timeout = new Timeout(() => {}, 0, SchedulePolicy.OnDemand); | ||
@@ -100,3 +101,3 @@ // Act | ||
// Arrange | ||
const timeout = new Timeout(() => {}, 500, false); | ||
const timeout = new Timeout(() => {}, 500, SchedulePolicy.OnDemand); | ||
@@ -147,3 +148,3 @@ // Act | ||
const action = jest.fn(); | ||
const timeout = new Timeout(action, 500, false); | ||
const timeout = new Timeout(action, 500, SchedulePolicy.OnDemand); | ||
timeout.set(); | ||
@@ -175,3 +176,3 @@ jest.runOnlyPendingTimers(); | ||
it("should invoke the action if resolve is true", () => { | ||
it("should invoke the action if clear policy is ClearPolicy.Resolve", () => { | ||
// Arrange | ||
@@ -183,3 +184,3 @@ const action = jest.fn(); | ||
// Act | ||
timeout.clear(true); | ||
timeout.clear(ClearPolicy.Resolve); | ||
jest.runOnlyPendingTimers(); | ||
@@ -191,9 +192,13 @@ | ||
it("should not invoke the action if resolve is false", () => { | ||
it("should not invoke the action if clear policy is ClearPolicy.Cancel", () => { | ||
// Arrange | ||
const action = jest.fn(); | ||
const timeout = new Timeout(action, 500, true); | ||
const timeout = new Timeout( | ||
action, | ||
500, | ||
SchedulePolicy.Immediately, | ||
); | ||
// Act | ||
timeout.clear(false); | ||
timeout.clear(ClearPolicy.Cancel); | ||
jest.runOnlyPendingTimers(); | ||
@@ -208,6 +213,6 @@ | ||
const action = jest.fn(); | ||
const timeout = new Timeout(action, 500, false); | ||
const timeout = new Timeout(action, 500, SchedulePolicy.OnDemand); | ||
// Act | ||
timeout.clear(true); | ||
timeout.clear(ClearPolicy.Resolve); | ||
jest.runOnlyPendingTimers(); | ||
@@ -214,0 +219,0 @@ |
@@ -11,2 +11,3 @@ // @flow | ||
IScheduleActions, | ||
Options, | ||
} from "./types.js"; | ||
@@ -21,12 +22,18 @@ | ||
export default class ActionScheduler implements IScheduleActions { | ||
_disabled: boolean = false; | ||
_registeredActions: Array<() => void> = []; | ||
static +NoopAction: ITimeout & IAnimationFrame & IInterval = { | ||
set: () => {}, | ||
get isSet() { | ||
return false; | ||
}, | ||
clear: () => {}, | ||
}; | ||
timeout( | ||
action: () => mixed, | ||
period: number, | ||
autoSchedule?: boolean, | ||
resolveOnClear?: boolean, | ||
): ITimeout { | ||
const timeout = new Timeout(action, period, autoSchedule); | ||
this._registeredActions.push(() => timeout.clear(resolveOnClear)); | ||
timeout(action: () => mixed, period: number, options?: Options): ITimeout { | ||
if (this._disabled) { | ||
return ActionScheduler.NoopAction; | ||
} | ||
const timeout = new Timeout(action, period, options?.schedulePolicy); | ||
this._registeredActions.push(() => timeout.clear(options?.clearPolicy)); | ||
return timeout; | ||
@@ -38,7 +45,11 @@ } | ||
period: number, | ||
autoSchedule?: boolean, | ||
resolveOnClear?: boolean, | ||
options?: Options, | ||
): IInterval { | ||
const interval = new Interval(action, period, autoSchedule); | ||
this._registeredActions.push(() => interval.clear(resolveOnClear)); | ||
if (this._disabled) { | ||
return ActionScheduler.NoopAction; | ||
} | ||
const interval = new Interval(action, period, options?.schedulePolicy); | ||
this._registeredActions.push(() => | ||
interval.clear(options?.clearPolicy), | ||
); | ||
return interval; | ||
@@ -49,8 +60,13 @@ } | ||
action: (DOMHighResTimeStamp) => void, | ||
autoSchedule?: boolean, | ||
resolveOnClear?: boolean, | ||
options?: Options, | ||
): IAnimationFrame { | ||
const animationFrame = new AnimationFrame(action, autoSchedule); | ||
if (this._disabled) { | ||
return ActionScheduler.NoopAction; | ||
} | ||
const animationFrame = new AnimationFrame( | ||
action, | ||
options?.schedulePolicy, | ||
); | ||
this._registeredActions.push(() => | ||
animationFrame.clear(resolveOnClear), | ||
animationFrame.clear(options?.clearPolicy), | ||
); | ||
@@ -65,2 +81,11 @@ return animationFrame; | ||
} | ||
/** | ||
* Prevents this scheduler from creating any additional actions. | ||
* This also clears any pending actions. | ||
*/ | ||
disable(): void { | ||
this._disabled = true; | ||
this.clearAll(); | ||
} | ||
} |
// @flow | ||
import type {IAnimationFrame} from "./types.js"; | ||
import { | ||
SchedulePolicy as SchedulePolicies, | ||
ClearPolicy as ClearPolicies, | ||
} from "./policies.js"; | ||
import type {IAnimationFrame, SchedulePolicy, ClearPolicy} from "./types.js"; | ||
/** | ||
@@ -22,5 +27,6 @@ * Encapsulates everything associated with calling requestAnimationFrame/ | ||
* @param {DOMHighResTimeStamp => mixed} action The action to be invoked. | ||
* @param {boolean} [autoSchedule] When true, the request is made immediately on | ||
* instanstiation; otherwise, `set` must be called to make the request. | ||
* Defaults to `true`. | ||
* @param {SchedulePolicy} [schedulePolicy] When SchedulePolicy.Immediately, | ||
* the interval is set immediately on instantiation; otherwise, `set` must be | ||
* called to set the interval. | ||
* Defaults to `SchedulePolicy.Immediately`. | ||
* @memberof AnimationFrame | ||
@@ -30,3 +36,3 @@ */ | ||
action: (DOMHighResTimeStamp) => mixed, | ||
autoSchedule?: boolean, | ||
schedulePolicy: SchedulePolicy = SchedulePolicies.Immediately, | ||
) { | ||
@@ -39,3 +45,3 @@ if (typeof action !== "function") { | ||
if (autoSchedule || autoSchedule == null) { | ||
if (schedulePolicy === SchedulePolicies.Immediately) { | ||
this.set(); | ||
@@ -67,6 +73,6 @@ } | ||
if (this.isSet) { | ||
this.clear(false); | ||
this.clear(ClearPolicies.Cancel); | ||
} | ||
this._animationFrameId = requestAnimationFrame((time) => | ||
this.clear(true, time), | ||
this.clear(ClearPolicies.Resolve, time), | ||
); | ||
@@ -81,5 +87,9 @@ } | ||
* | ||
* @param {boolean} [resolve] When true, if the request was pending when | ||
* called, the request action is invoked after cancelling the timeout. | ||
* Defaults to false. | ||
* @param {ClearPolicy} [policy] When ClearPolicy.Resolve, if the request | ||
* was set when called, the request action is invoked after cancelling | ||
* the request; otherwise, the pending action is cancelled. | ||
* Defaults to `ClearPolicy.Cancel`. | ||
* @param {DOMHighResTimeStamp} [time] Timestamp to pass to the action when | ||
* ClearPolicy.Resolve is specified. Ignored when ClearPolicy.Cancel is | ||
* specified. | ||
* | ||
@@ -89,3 +99,6 @@ * @returns {void} | ||
*/ | ||
clear(resolve?: boolean, time?: DOMHighResTimeStamp): void { | ||
clear( | ||
policy: ClearPolicy = ClearPolicies.Cancel, | ||
time?: DOMHighResTimeStamp, | ||
): void { | ||
const animationFrameId = this._animationFrameId; | ||
@@ -97,3 +110,3 @@ this._animationFrameId = null; | ||
cancelAnimationFrame(animationFrameId); | ||
if (resolve) { | ||
if (policy === ClearPolicies.Resolve) { | ||
this._action(time || performance.now()); | ||
@@ -100,0 +113,0 @@ } |
// @flow | ||
import type {IInterval} from "./types.js"; | ||
import { | ||
SchedulePolicy as SchedulePolicies, | ||
ClearPolicy as ClearPolicies, | ||
} from "./policies.js"; | ||
import type {IInterval, SchedulePolicy, ClearPolicy} from "./types.js"; | ||
/** | ||
@@ -25,6 +30,6 @@ * Encapsulates everything associated with calling setInterval/clearInterval, | ||
* @param {number} intervalMs The interval period. | ||
* @param {boolean} [autoSchedule] When true, the interval is activated | ||
* immediately on instanstiation; otherwise, `set` must be called to | ||
* activate the interval. | ||
* Defaults to `true`. | ||
* @param {SchedulePolicy} [schedulePolicy] When SchedulePolicy.Immediately, | ||
* the interval is set immediately on instantiation; otherwise, `set` must be | ||
* called to set the interval. | ||
* Defaults to `SchedulePolicy.Immediately`. | ||
* @memberof Interval | ||
@@ -35,3 +40,3 @@ */ | ||
intervalMs: number, | ||
autoSchedule?: boolean, | ||
schedulePolicy: SchedulePolicy = SchedulePolicies.Immediately, | ||
) { | ||
@@ -49,3 +54,3 @@ if (typeof action !== "function") { | ||
if (autoSchedule || autoSchedule == null) { | ||
if (schedulePolicy === SchedulePolicies.Immediately) { | ||
this.set(); | ||
@@ -75,3 +80,3 @@ } | ||
if (this.isSet) { | ||
this.clear(false); | ||
this.clear(ClearPolicies.Cancel); | ||
} | ||
@@ -87,5 +92,6 @@ this._intervalId = setInterval(() => this._action(), this._intervalMs); | ||
* | ||
* @param {boolean} [resolve] When true, if the interval was active when | ||
* called, the interval action is invoked after cancellation. Defaults to | ||
* false. | ||
* @param {ClearPolicy} [policy] When ClearPolicy.Resolve, if the request | ||
* was set when called, the request action is invoked after cancelling | ||
* the request; otherwise, the pending action is cancelled. | ||
* Defaults to `ClearPolicy.Cancel`. | ||
* | ||
@@ -95,3 +101,3 @@ * @returns {void} | ||
*/ | ||
clear(resolve?: boolean): void { | ||
clear(policy: ClearPolicy = ClearPolicies.Cancel): void { | ||
const intervalId = this._intervalId; | ||
@@ -103,3 +109,3 @@ this._intervalId = null; | ||
clearInterval(intervalId); | ||
if (resolve) { | ||
if (policy === ClearPolicies.Resolve) { | ||
this._action(); | ||
@@ -106,0 +112,0 @@ } |
// @flow | ||
import type {ITimeout} from "./types.js"; | ||
import { | ||
SchedulePolicy as SchedulePolicies, | ||
ClearPolicy as ClearPolicies, | ||
} from "./policies.js"; | ||
import type {ITimeout, SchedulePolicy, ClearPolicy} from "./types.js"; | ||
/** | ||
@@ -25,5 +30,6 @@ * Encapsulates everything associated with calling setTimeout/clearTimeout, and | ||
* @param {number} timeoutMs The timeout period. | ||
* @param {boolean} [autoSchedule] When true, the timer is set immediately on | ||
* instanstiation; otherwise, `set` must be called to set the timeout. | ||
* Defaults to `true`. | ||
* @param {SchedulePolicy} [schedulePolicy] When SchedulePolicy.Immediately, | ||
* the timer is set immediately on instantiation; otherwise, `set` must be | ||
* called to set the timeout. | ||
* Defaults to `SchedulePolicy.Immediately`. | ||
* @memberof Timeout | ||
@@ -34,3 +40,3 @@ */ | ||
timeoutMs: number, | ||
autoSchedule?: boolean, | ||
schedulePolicy: SchedulePolicy = SchedulePolicies.Immediately, | ||
) { | ||
@@ -48,3 +54,3 @@ if (typeof action !== "function") { | ||
if (autoSchedule || autoSchedule == null) { | ||
if (schedulePolicy === SchedulePolicies.Immediately) { | ||
this.set(); | ||
@@ -76,5 +82,8 @@ } | ||
if (this.isSet) { | ||
this.clear(false); | ||
this.clear(ClearPolicies.Cancel); | ||
} | ||
this._timeoutId = setTimeout(() => this.clear(true), this._timeoutMs); | ||
this._timeoutId = setTimeout( | ||
() => this.clear(ClearPolicies.Resolve), | ||
this._timeoutMs, | ||
); | ||
} | ||
@@ -88,5 +97,6 @@ | ||
* | ||
* @param {boolean} [resolve] When true, if the timeout was set when called, | ||
* the timeout action is invoked after cancelling the timeout. Defaults to | ||
* false. | ||
* @param {ClearPolicy} [policy] When ClearPolicy.Resolve, if the request | ||
* was set when called, the request action is invoked after cancelling | ||
* the request; otherwise, the pending action is cancelled. | ||
* Defaults to `ClearPolicy.Cancel`. | ||
* | ||
@@ -96,3 +106,3 @@ * @returns {void} | ||
*/ | ||
clear(resolve?: boolean): void { | ||
clear(policy: ClearPolicy = ClearPolicies.Cancel): void { | ||
const timeoutId = this._timeoutId; | ||
@@ -104,3 +114,3 @@ this._timeoutId = null; | ||
clearTimeout(timeoutId); | ||
if (resolve) { | ||
if (policy === ClearPolicies.Resolve) { | ||
this._action(); | ||
@@ -107,0 +117,0 @@ } |
// @flow | ||
export type SchedulePolicy = "schedule-immediately" | "schedule-on-demand"; | ||
export type ClearPolicy = "resolve-on-clear" | "cancel-on-clear"; | ||
/** | ||
@@ -38,9 +41,10 @@ * Encapsulates everything associated with calling setTimeout/clearTimeout, and | ||
* | ||
* @param {boolean} [resolve] When true, if the timeout was set when called, | ||
* the timeout action is invoked after cancelling the timeout. Defaults to | ||
* false. | ||
* @param {ClearPolicy} [policy] When ClearPolicy.Resolve, if the request | ||
* was set when called, the request action is invoked after cancelling | ||
* the request; otherwise, the pending action is cancelled. | ||
* Defaults to `ClearPolicy.Cancel`. | ||
* | ||
* @memberof ITimeout | ||
*/ | ||
clear(resolve?: boolean): void; | ||
clear(policy?: ClearPolicy): void; | ||
} | ||
@@ -81,9 +85,10 @@ | ||
* | ||
* @param {boolean} [resolve] When true, if the interval was active when | ||
* called, the associated action is invoked after cancelling the interval. | ||
* Defaults to false. | ||
* @param {ClearPolicy} [policy] When ClearPolicy.Resolve, if the request | ||
* was set when called, the request action is invoked after cancelling | ||
* the request; otherwise, the pending action is cancelled. | ||
* Defaults to `ClearPolicy.Cancel`. | ||
* | ||
* @memberof IInterval | ||
*/ | ||
clear(resolve?: boolean): void; | ||
clear(policy?: ClearPolicy): void; | ||
} | ||
@@ -126,11 +131,17 @@ | ||
* | ||
* @param {boolean} [resolve] When true, if the request was set when called, | ||
* the request action is invoked after cancelling the request. Defaults to | ||
* false. | ||
* @param {ClearPolicy} [policy] When ClearPolicy.Resolve, if the request | ||
* was set when called, the request action is invoked after cancelling | ||
* the request; otherwise, the pending action is cancelled. | ||
* Defaults to `ClearPolicy.Cancel`. | ||
* | ||
* @memberof IAnimationFrame | ||
*/ | ||
clear(resolve?: boolean): void; | ||
clear(policy?: ClearPolicy): void; | ||
} | ||
export type Options = {| | ||
schedulePolicy?: SchedulePolicy, | ||
clearPolicy?: ClearPolicy, | ||
|}; | ||
/** | ||
@@ -167,8 +178,3 @@ * Provides means to request timeouts, intervals, and animation frames, with | ||
*/ | ||
timeout( | ||
action: () => mixed, | ||
period: number, | ||
autoSchedule?: boolean, | ||
resolveOnClear?: boolean, | ||
): ITimeout; | ||
timeout(action: () => mixed, period: number, options?: Options): ITimeout; | ||
@@ -196,8 +202,3 @@ /** | ||
*/ | ||
interval( | ||
action: () => mixed, | ||
period: number, | ||
autoSchedule?: boolean, | ||
resolveOnClear?: boolean, | ||
): IInterval; | ||
interval(action: () => mixed, period: number, options?: Options): IInterval; | ||
@@ -224,4 +225,3 @@ /** | ||
action: (time: DOMHighResTimeStamp) => void, | ||
autoSchedule?: boolean, | ||
resolveOnClear?: boolean, | ||
options?: Options, | ||
): IAnimationFrame; | ||
@@ -228,0 +228,0 @@ |
115183
25
2589