[Medium] LeetCode JS 30 - 2637. Promise Time Limit

March 6, 2024

☕️ Support Us
Your support will help us to continue to provide quality content.👉 Buy Me a Coffee

LeetCode 30 Days of JavaScript

This question is from LeetCode's 30 Days of JavaScript Challenge

2637. Promise Time Limit

Question Prompt

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".
// 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.

Solutions

To solve this question, we need to understand JavaScript Promise and Promise.race first.

A Promise in JavaScript represents the eventual outcome of an asynchronous operation. Promises have three primary states:

  • Pending: The initial state while the operation is ongoing.
  • Fulfilled: The operation completed successfully, and a value is available.
  • Rejected: The operation failed, and an error reason is available.

Promise.race() is a method that takes a set of promises and returns a new promise. The key: This new promise will resolve or reject as soon as one of the promises in the set settles (is either fulfilled or rejected). That's where the 'race' metaphor comes in!

To put in into practice, we can first define a timeLimt function. It takes the original function (fn) and the time limit (t) as input. And it will return a function.

The inner function will have two promises within it.

  • First, timeoutPromise: This promise, after a delay of t milliseconds, will reject with the "Time Limit Exceeded" message.
  • fnPromise: The execution of the function fn

Then, Promise.race() sets up a race between the fnPromise (our function execution) and the timeoutPromise. If fn completes before the timeout The returned promise from withTimeout will resolve with the result of the original function. And, if fn takes too long, the timeoutPromise will reject first, and the returned promise from withTimeout will reject with the "Time Limit Exceeded" error.

var timeLimit = function (fn, t) {
  // Return a function that takes arguments
  return (...args) => {
    // Create a timeout promise that rejects after `t` milliseconds
    const timeoutPromise = new Promise((resolve, reject) => {
      setTimeout(() => reject("Time Limit Exceeded"), t);
    });

    // Promise representing the function execution
    const fnPromise = fn(...args);

    // Return a promise that races the function execution against the timeout
    return Promise.race([fnPromise, timeoutPromise]);
  };
};
☕️ Support Us
Your support will help us to continue to provide quality content.👉 Buy Me a Coffee