Here are the challenge directions:
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".
I’ve tried these two bits of code:
// Function to return new time limited version of input function
const timeLimit = function(fn, t) {
// Outer asynchronous function
async function timeLimited(...args) {
// Set start time to current time
let startTime = Date.now()
// Wait to get fulfillment value from function parameter
const result = await fn(...args);
// Duration will be current time minus the start time
let duration = Date.now() - startTime;
/* If duration is greater than the time parameter,
throw time limit excession error */
if (duration > t) throw new Error("Time Limit Exceeded");
// Else return the result of the await function
else return result;
};
// Return the asynchronous time-limited function
return timeLimited; };
But I get this:
Output:
{"rejected":{},"time":100}
Expected:
{"rejected":"Time Limit Exceeded","time":50}
// Function·to·return·new·time·limited·version·of·input·function
const timeLimit = function(fn, t) {
// Boolean to say error is false or true
let hasError = false;
// Outer asynchronous function
async function timeLimited(...args) {
// Set timer ID
const timerId = setTimeout(() => hasError = true, t);
// Constant to hold result
const result = fn(...args);
// Clear timeout
clearTimeOut(timerId);
// If there is an error, throw it
if (hasError) throw new Error("Time Limit Exceeded");
// Else return the result of the await function
else return result;
};
// Return time limited function
return timeLimited; };
But I get this:
Runtime Error
(node:21) Warning: Accessing non-existent property 'ListNode' of module exports inside circular dependency
(Use `nodejs run --trace-warnings ...` to show where the warning was created)
(node:21) Warning: Accessing non-existent property 'TreeNode' of module exports inside circular dependency
(node:21) Warning: Accessing non-existent property 'NestedInteger' of module exports inside circular dependency
node:internal/process/promises:289
triggerUncaughtException(err, true /* fromPromise */);
^
[UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "Error".] {
code: 'ERR_UNHANDLED_REJECTION'
}
Node.js v20.10.0
Here are the test cases:
const limited = timeLimit((t) => new Promise(res => setTimeout(res, t)), 100);
limited(150).catch(console.log); // "Time Limit Exceeded" at t=100ms
If anyone could help me fix my code, I would appreciate it.
2
Answers
You will have to create your own custom error message like below:
Both attempts have some common and some different problems:
The common problems:
Error
object, while the challenge says that the rejection reason should be a string. This is why you see"rejected":{}
in the output object. So don’t donew Error
.this
argument is passed correctly tofn
, then this is an issue in your code: it does not pass thethis
argument. To achieve that you should work withfn.call
orfn.apply
.Then to the specific problems:
The first attempt has this issue:
await
has no knowledge of the time-out and so the async function will only resume whenfn
resolves, which might be well beyond the time-out period. And so the time at which the rejection is triggered is too late. The testing framework detects this time difference.The second attempt:
clearTimeOut
, and so this will immediately trigger a runtime error, which apparently is leading to further unhandled errors in the asynchronous part of the testing code.clearTimeout
andif (hasError)
. This means thesetTimeout
callback will never run, and even if it did, you already checkedhasError
before it could ever run, and it will always befalse
. Therefore this version of the code will never return a promise that gets rejected with "Time Limit Exceeded".This kind of time-out behaviour can be implemented with
Promise.race
: you provide it thefn
promise and a promise that will reject after the time-out. Whichever resolves first will determine the resolution of the promise thatPromise.race
returns.Here is how that would look: