LeetCode JavaScript 30 Days Challenge – Day12 – 2637. Promise Time Limit

    LeetCode JavaScript 30 Days Challenge

    Given an asynchronous function fn and a time t in milliseconds, return a new time limited version of the input function.
    A time limited function is a function that is identical to the original unless it takes longer than t milliseconds to fullfill.
    In that case, it will reject with “Time Limit Exceeded”.
    Note that it should reject with a string, not an Error.

    給予一個非同步的函式 fn 和一個以豪秒為單位的時間 t,回傳一個新的限時函式。
    這個限時函式和原始函式完全相同,除非它超過 t 豪秒才能完成,
    在這個情況下,它將拒絕並顯示“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}
    

    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}
    

    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}
    

    Example 4:

    Input: 
    fn = async () => { 
      throw "Error";
    }
    inputs = []
    t = 1000
    Output: {"rejected":"Error","time":0}
    

    solution:
    以 Example 1 為例,呼叫 limited() 函式後,
    進入到 timeLimit() 中建立一個含有 setTimeout() 的 new Promise(),
    如果時間經過 t 豪秒後會執行 reject(“Time Limit Exceeded”)。
    而 fn 函式放入 …args,並等待 100 豪秒後回傳 n * n,
    此時因為超過 50 豪秒的時間限制,而 .catch(console.log) 抓取到 reject 的結果,
    故回傳(“Time Limit Exceeded”)訊息。
    ex.如果 fn(…args) 提前完成,則需取消 id 的限時函式。

    Code 1: BigO(1)

    var timeLimit = function(fn, t) {
        return async function(...args) {
            return new Promise((resolve, reject) => {
                const id = setTimeout(() => reject("Time Limit Exceeded"), t);
                fn(...args)
                    .then((res) => resolve(res))
                    .catch((err) => reject(err))
                    .finally(() => clearTimeout(id))
            })
        }
    };
    

    FlowChart:
    Example 1

    const limited = timeLimit(async (n) => {
      await new Promise((res) => setTimeout(res, 100));
      return n * n;
    }, 50);
    limited(5).catch(console.log); // "Time Limit Exceeded" at t=50ms
    

    Example 2

    const limited = timeLimit(async (n) => {
      await new Promise((res) => setTimeout(res, 100));
      return n * n;
    }, 150);
    limited(5).then(console.log).catch(console.log); // return 25 at t=100ms
    

    Example 3

    const limited = timeLimit(async (a, b) => {
      await new Promise((res) => setTimeout(res, 120));
      return a + b;
    }, 150);
    limited(5, 10).then(console.log).catch(console.log); // return 15 at t=120ms
    

    Example 4

    const limited = timeLimit(async () => {
      throw "Error";
    }, 1000);
    limited().then(console.log).catch(console.log); // "Error" at t=0ms