Given an asynchronous function fn and a time t in milliseconds, return a new time limited version of the input function. fn takes arguments provided to the time limited function.
The time limited function should follow these rules:
fn completes within the time limit of t milliseconds, the time limited function should resolve with the result.fn exceeds the time limit, the time limited function should reject with the string "Time Limit Exceeded".
Example 1:
Input:
fn = async (n) => {
await new Promise(res => setTimeout(res, 100));
return n * n;
}
inputs = [5]
t = 50
Output: {"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 = 150
Output: {"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 = 150
Output: {"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 = 1000
Output: {"rejected":"Error","time":0}
Explanation:
The function immediately throws an error.
Constraints:
0 <= inputs.length <= 100 <= t <= 1000fn returns a promiseThis approach leverages the Promise.race() function to race between the original asynchronous function and a timeout promise. If the function executes within the time limit, it resolves with the function's result. Otherwise, the timeout promise rejects with "Time Limit Exceeded."
This code wraps the original function within an asynchronous function that introduces a race condition between the function and a timeout duration using Promise.race(). If fn completes within t milliseconds, its resolved value is returned; otherwise, it gets rejected.
Time Complexity: O(1) — The best and worst case are consistent as it relies on how quickly the promise in fn resolves.
Space Complexity: O(1) — A constant amount of additional space is used.
This approach manually sets a timeout before invoking the asynchronous function and uses the result as a flag to determine if it has been reached. If the function attempt completes before the timeout, it clears the timeout; otherwise, it signals a reject using the timeout handler.
The code demonstrates a manual timeout mechanism coupled with Promise.race(). It introduces a timeout and clears it in finally to ensure the resource management is maintained cleanly. Upon completion of the main promise or timeout, it uses clearTimeout to avoid any further actions on the timer.
Time Complexity: O(1) — Performance does not vary significantly with time limit or function complexity.
Space Complexity: O(1) — Additional space is minimally affected by handling timeouts.
This approach utilizes Promise.race to handle the timeout. Promise.race allows us to race the original function's promise against a new promise that rejects after the specified duration t. If the original function resolves before the timeout, the new function resolves successfully. Otherwise, it rejects with a timeout error.
The function timeLimit wraps the original asynchronous function fn. It returns an asynchronous function that races fn(...args) with a timeout promise. The timeout promise calls setTimeout, which rejects after t milliseconds. If fn(...args) resolves before the timeout, the Promise.race resolves; otherwise, it rejects.
Time Complexity: O(1) — Relying on JavaScript's Promise system, where each promise has a negligible overhead.
Space Complexity: O(1) — Constant space used primarily for the setTimeout and the Promise itself.
This approach manually controls the timeout by creating a new promise that listens to both the resolution of fn and the timeout. By tracking which occurs first, we either resolve or reject appropriately. This approach sorts out through manual management of completion signals.
The function timeLimit creates and returns a new promise containing the logic to handle both the execution of fn and the timeout. It uses a flag isResolved to ensure that only the first completion (either the resolution of the fn function or the setTimeout) is applied. If the fn function resolves or rejects before the timeout, it handles those outcomes. Otherwise, it eventually triggers the timeout rejection.
Time Complexity: O(1) — The complexity is based on the constant time operations, with the Promise system operation being negligible.
Space Complexity: O(1) — Uses constant space for the timeout tracking and signal flags.
| Approach | Complexity |
|---|---|
| Approach 1: Using Promise.race() | Time Complexity: O(1) — The best and worst case are consistent as it relies on how quickly the promise in |
| Approach 2: Using Manual Timeout Handling | Time Complexity: O(1) — Performance does not vary significantly with time limit or function complexity. |
| Promise.race for Timeout | Time Complexity: O(1) — Relying on JavaScript's Promise system, where each promise has a negligible overhead. |
| Manual Promise Handling | Time Complexity: O(1) — The complexity is based on the constant time operations, with the Promise system operation being negligible. |
Promise Time Limit - Leetcode 2637 - JavaScript 30-Day Challenge • NeetCodeIO • 10,664 views views
Watch 9 more video solutions →Practice Promise Time Limit with our built-in code editor and test cases.
Practice on FleetCodePractice this problem
Open in Editor