
Problem Statement
In the given setup, our objective is to create a wrapper for an asynchronous function fn, which conforms to a specific time constraint, t milliseconds. The wrapped function, or the time limited function, needs to behave in a particular manner based on the execution duration of fn concerning the time limit t.
The behavior is defined as:
- If the asynchronous function
fnsuccessfully completes its execution within the predefined time span,tmilliseconds, then the time limited function should resolve and return the outcome offn. - Conversely, if
fndoes not finish within the specifiedtmilliseconds, the time limited function should reject and provide a message stating"Time Limit Exceeded".
Examples
Example 1
Input:
fn = async (n) => {
await new Promise(res => setTimeout(res, 100));
return n * n;
}
inputs = [5]
t = 50Output:
{"rejected":"Time Limit Exceeded","time":50}Explanation:
const limited = timeLimit(fn, t)
const start = performance.now()
let result;
try {
const res = await limited(...inputs)
result = {"resolved": res, "time": Math.floor(performance.now() - start)};
} catch (err) {
result = {"rejected": err, "time": Math.floor(performance.now() - start)};
}
console.log(result) // Output
The provided function is set to resolve after 100ms. However, the time limit is set to 50ms. It rejects at t=50ms because the time limit was reached.Example 2
Input:
fn = async (n) => {
await new Promise(res => setTimeout(res, 100));
return n * n;
}
inputs = [5]
t = 150Output:
{"resolved":25,"time":100}Explanation:
The function resolved 5 * 5 = 25 at t=100ms. The time limit is never reached.
Example 3
Input:
fn = async (a, b) => {
await new Promise(res => setTimeout(res, 120));
return a + b;
}
inputs = [5,10]
t = 150Output:
{"resolved":15,"time":120}Explanation:
The function resolved 5 + 10 = 15 at t=120ms. The time limit is never reached.
Example 4
Input:
fn = async () => {
throw "Error";
}
inputs = []
t = 1000Output:
{"rejected":"Error","time":0}Explanation:
The function immediately throws an error.
Constraints
0 <= inputs.length <= 100 <= t <= 1000fnreturns a promise
Approach and Intuition
The examples provided clarify the operational semantics of the time limited function through various function scenarios:
Example 1:
- The function
fn, which squares the numbern, is designed to complete after 100 milliseconds. However, the set time limittis only 50 milliseconds. - Outcome: Since the function exceeds the specified limit, it is halted, and a rejection with the message
"Time Limit Exceeded"is returned.
- The function
Example 2:
- Here, the same function
fnis used but with an extended time limittof 150 milliseconds. - Outcome: The function executes within the allowed time (100 milliseconds), returning the result
25(5 squared), and does not exceed the time limit.
- Here, the same function
Example 3:
- A function that sums two numbers,
aandb, taking 120 milliseconds to complete execution. - Outcome: With the time limit set at 150 milliseconds, the function completes successfully and returns the sum
15within the permissible timeframe.
- A function that sums two numbers,
Example 4:
- An asynchronous function that throws an error immediately.
- Outcome: Even though the time limit
tis generous (1000ms), the function rejects immediately due to an exception, thus returning"Error".
The key points to manage in implementation would be:
- Setting up a timer that checks if the
fnhas resolved or rejected before the elapsed timet. - If the time
telapses beforefnconcludes, the wrapper needs to reject without waiting further. - The need for accurate timing hints at using a promise racing strategy, wherein the promise that resolves or rejects first (either
fn's promise or the timeout promise) determines the output.
Considering the constraints, such as the maximum allowable input length and time t, our approach should efficiently manage multiple arguments for fn and handle varying execution times without compromising performance.
Solutions
- JavaScript
var setTimeoutPromise = function(func, timeoutDuration) {
return async function(...parameters) {
return new Promise(async (resolve, reject) => {
const timeoutHandler = setTimeout(() => {
reject("Time Limit Exceeded");
}, timeoutDuration);
try {
const output = await func(...parameters);
resolve(output);
} catch(error) {
reject(error);
}
clearTimeout(timeoutHandler);
});
};
};
The provided JavaScript code introduces a function called setTimeoutPromise which transforms any function into a promise-based timeout function. This is especially useful in situations where functions may need time limits.
setTimeoutPromisetakes two parameters:func: The function you want to execute.timeoutDuration: The maximum time allowed forfuncto execute before considering it timed out.
The
setTimeoutPromisereturns a new asynchronous function which takes any number of arguments (parameters). This new function does the following:- Initializes a
Promise. - Sets a timeout using
setTimeout. If the function execution exceeds the allowedtimeoutDuration, the promise rejects with a"Time Limit Exceeded"message. - Executes the provided
funcwith passed parameters and awaits its completion. - If
funcexecutes successfully within the timeout, the promise resolves with the result offunc. - If an error occurs during the execution of
func, the promise rejects with the encountered error. - Finally,
clearTimeoutis called to clear the timer iffunchas completed successfully or thrown an error before the timer expires.
- Initializes a
This function is highly useful in scenarios where timing constraints are critical, such as in API requests, heavy computational functions, or operations prone to potentially long delays. By using this setup, you effectively manage and control execution flow in asynchronous JavaScript environments, ensuring that operations do not exceed a certain time limit.