Watch 10 video solutions for Promise Time Limit, a medium level problem. This walkthrough by NeetCodeIO has 12,251 views views. Want to try solving it yourself? Practice on FleetCode or read the detailed text solution.
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 promiseProblem Overview: You are given an asynchronous function fn and a time limit t. The goal is to return a new function that runs fn but rejects with "Time Limit Exceeded" if the promise does not resolve within t milliseconds.
Approach 1: Using Promise.race() (O(1) time, O(1) space)
The cleanest solution uses Promise.race(). Create two promises: one from the original function call fn(...args) and another timeout promise created with setTimeout that rejects after t milliseconds. Promise.race() resolves or rejects with whichever promise finishes first. If the function finishes before the timer, its result is returned. If the timer fires first, the wrapper rejects with the timeout error.
This approach relies on JavaScript's asynchronous event loop and promise scheduling. The key insight is that Promise.race() automatically handles the "first completed" behavior without manual state checks. It keeps the implementation small and readable, which is why it is the most common pattern used in real-world JavaScript systems when enforcing API or task deadlines.
Conceptually this pattern appears frequently in JavaScript async utilities and libraries that implement request timeouts or cancellation behavior around promises.
Approach 2: Manual Timeout Handling (O(1) time, O(1) space)
This approach manually constructs a new Promise and controls when it resolves or rejects. Inside the promise executor, start a setTimeout that triggers rejection after t milliseconds. Then execute fn(...args) and attach .then() and .catch() handlers. If the function finishes first, clear the timer using clearTimeout and resolve with the returned value.
This version gives you explicit control over the lifecycle of the timer and result propagation. The logic ensures only one outcome happens: either the timeout fires or the function completes. Manual handling is useful when implementing custom async utilities or debugging complex asynchronous programming flows where more control is needed beyond Promise.race().
Recommended for interviews: The Promise.race() solution is usually expected. It demonstrates that you understand promise composition and async control flow in JavaScript. Mentioning the manual timeout version shows deeper understanding of how promises and timers interact, but interviewers generally prefer the concise race-based implementation.
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Promise.race Timeout | O(1) | O(1) | Best general solution. Clean and concise way to enforce async time limits. |
| Manual Promise Timeout Handling | O(1) | O(1) | Useful when you need explicit control over timers and promise resolution. |