
Problem Statement
In this task, we are given a function fn
along with an array args
containing its arguments, and a specific time interval t
. The objective is to construct and return a cancel function, cancelFn
, that when invoked, stops the periodic execution of fn
. Initially, fn
is executed with the arguments from args
and then repeatedly executed after every t
milliseconds. This periodic invocation continues until cancelFn
is triggered at a specified delay cancelTimeMs
, which halts further executions of fn
.
The challenge encompasses setting up the initial and periodic invocation of fn
using JavaScript's setTimeout
or similar mechanism, and managing its cancellation after cancelTimeMs
has elapsed using the cancelFn
function.
Examples
Example 1
Input:
fn = (x) => x * 2, args = [4], t = 35
Output:
[ {"time": 0, "returned": 8}, {"time": 35, "returned": 8}, {"time": 70, "returned": 8}, {"time": 105, "returned": 8}, {"time": 140, "returned": 8}, {"time": 175, "returned": 8} ]
Explanation:
const cancelTimeMs = 190; const cancelFn = cancellable((x) => x * 2, [4], 35); setTimeout(cancelFn, cancelTimeMs); Every 35ms, fn(4) is called. Until t=190ms, then it is cancelled. 1st fn call is at 0ms. fn(4) returns 8. 2nd fn call is at 35ms. fn(4) returns 8. 3rd fn call is at 70ms. fn(4) returns 8. 4th fn call is at 105ms. fn(4) returns 8. 5th fn call is at 140ms. fn(4) returns 8. 6th fn call is at 175ms. fn(4) returns 8. Cancelled at 190ms
Example 2
Input:
fn = (x1, x2) => (x1 * x2), args = [2, 5], t = 30
Output:
[ {"time": 0, "returned": 10}, {"time": 30, "returned": 10}, {"time": 60, "returned": 10}, {"time": 90, "returned": 10}, {"time": 120, "returned": 10}, {"time": 150, "returned": 10} ]
Explanation:
const cancelTimeMs = 165; const cancelFn = cancellable((x1, x2) => (x1 * x2), [2, 5], 30) setTimeout(cancelFn, cancelTimeMs) Every 30ms, fn(2, 5) is called. Until t=165ms, then it is cancelled. 1st fn call is at 0ms 2nd fn call is at 30ms 3rd fn call is at 60ms 4th fn call is at 90ms 5th fn call is at 120ms 6th fn call is at 150ms Cancelled at 165ms
Example 3
Input:
fn = (x1, x2, x3) => (x1 + x2 + x3), args = [5, 1, 3], t = 50
Output:
[ {"time": 0, "returned": 9}, {"time": 50, "returned": 9}, {"time": 100, "returned": 9}, {"time": 150, "returned": 9} ]
Explanation:
const cancelTimeMs = 180; const cancelFn = cancellable((x1, x2, x3) => (x1 + x2 + x3), [5, 1, 3], 50) setTimeout(cancelFn, cancelTimeMs) Every 50ms, fn(5, 1, 3) is called. Until t=180ms, then it is cancelled. 1st fn call is at 0ms 2nd fn call is at 50ms 3rd fn call is at 100ms 4th fn call is at 150ms Cancelled at 180ms
Constraints
fn
is a functionargs
is a valid JSON array1 <= args.length <= 10
30 <= t <= 100
10 <= cancelTimeMs <= 500
Approach and Intuition
The objective is to implement a functionality where a function fn
can be scheduled to run at an interval of t
milliseconds and can be programmatically stopped at a specific time cancelTimeMs
. This can be visualized through two primary operations:
- Initial and Periodic Invocation:
- We immediately invoke the function
fn
with the provided argumentsargs
. - We then use JavaScript's
setInterval
to continue callingfn
everyt
milliseconds.
- We immediately invoke the function
- Cancellation:
- A cancel function,
cancelFn
, when executed, should useclearInterval
to stop any further executions scheduled bysetInterval
. - This
cancelFn
is scheduled to run aftercancelTimeMs
milliseconds usingsetTimeout
. Thus, ensuring no further calls tofn
occur past this point.
- A cancel function,
The examples provided simulate this behavior:
- Example 1: A multiplication function is invoked repeatedly every 35 milliseconds and stops at 190 milliseconds.
- Example 2: A product function for two numbers runs every 30 milliseconds and halts at 165 milliseconds.
- Example 3: A summation function runs every 50 milliseconds and is canceled at 180 milliseconds.
In each case, the output reflects the results of fn
at each invocation until it is stopped by cancelFn
. Each of these settings adheres to the specified constraints regarding the number of arguments, the interval t
, and the maximum duration before cancellation cancelTimeMs
.
Solutions
- JavaScript
/**
* @param {Function} functionToRun
* @param {Array} parameters
* @param {number} repeatTime
* @return {Function}
*/
var repeatableWithCancel = function(functionToRun, parameters, repeatTime) {
let currentTimer = null;
functionToRun(...parameters);
const initiateTimer = () => {
currentTimer = setTimeout(() => {
functionToRun(...parameters);
initiateTimer();
}, repeatTime);
};
initiateTimer();
const stopTimer = () => {
if (currentTimer !== null) {
clearTimeout(currentTimer);
}
};
return stopTimer;
};
The JavaScript solution provided defines a function called repeatableWithCancel
that accepts three parameters: functionToRun
, parameters
, and repeatTime
. This function is designed to repeatedly execute a specified function at defined intervals, which can be programmatically cancelled when needed.
Begin by defining the function
repeatableWithCancel
with three parameters:functionToRun
: The function you wish to execute repeatedly.parameters
: An array of arguments to pass to the function being invoked.repeatTime
: The time interval (in milliseconds) between successive invocations offunctionToRun
.
Inside
repeatableWithCancel
, initialize a variablecurrentTimer
tonull
, which will later store the reference to the timeout.Execute the
functionToRun
immediately with the providedparameters
using the spread syntax (...parameters
).Define
initiateTimer
, a function that sets a timeout which executesfunctionToRun
using the providedparameters
after a delay ofrepeatTime
, and recursively calls itself. This creates an indefinite loop of function execution at the specified interval.Initialize the timer with a call to
initiateTimer()
directly within therepeatableWithCancel
function.Define the function
stopTimer
which, when called, checks ifcurrentTimer
is notnull
and, if so, usesclearTimeout
to stop the timeout, effectively cancelling the repetitive execution.Return
stopTimer
fromrepeatableWithCancel
. This returned function can be called to stop the timer at any point, providing control over when to stop the repetitive actions.
This implementation allows the user to create a setup where function executions can be repeated at intervals with the flexibility to stop the repetition whenever required. Keep in mind to start the timer immediately and allow for its cancellation through the function returned by repeatableWithCancel
.
No comments yet.