problemmediumalgorithmsleetcode-2637leetcode 2637leetcode2637

Promise Time Limit

MediumUpdated: Aug 2, 2025
Practice on:

Problem

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:

  • If the fn completes within the time limit of t milliseconds, the time limited function should resolve with the result.
  • If the execution of the fn exceeds the time limit, the time limited function should reject with the string "Time Limit Exceeded".

Examples

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 <= 10
  • 0 <= t <= 1000
  • fn returns a promise

Solution

Method 1 – Promise.race with Timeout

Intuition

We want to run the original async function, but if it takes longer than t milliseconds, we should reject with "Time Limit Exceeded". This is a classic use case for Promise.race, where we race the original promise against a timeout promise.

Approach

  1. Return a new function that, when called, returns a Promise.
  2. Start the original function and a timeout promise in parallel.
  3. If the original function resolves or rejects before the timeout, propagate its result.
  4. If the timeout fires first, reject with the required message.

Code

JavaScript
/**
 * @param {Function} fn
 * @param {number} t
 * @return {Function}
 */
var timeLimit = function(fn, t) {
    return async function(...args) {
        return Promise.race([
            fn(...args),
            new Promise((_, reject) => setTimeout(() => reject("Time Limit Exceeded"), t))
        ]);
    }
};
TypeScript
function timeLimit<T extends (...args: any[]) => Promise<any>>(fn: T, t: number): (...args: Parameters<T>) => Promise<ReturnType<T> extends Promise<infer R> ? R : never> {
    return async (...args: Parameters<T>) => {
        return Promise.race([
            fn(...args),
            new Promise((_, reject) => setTimeout(() => reject("Time Limit Exceeded"), t))
        ]) as any;
    };
}

Complexity

  • ⏰ Time complexity: O(1) for the wrapper, plus the time taken by the original function.
  • 🧺 Space complexity: O(1) for the wrapper.

Comments