Problem: Chain Multiple Decorators on a Service Method
Problem statement
You’re working with a simulated service that fetches user data asynchronously. The team wants to add logging for visibility and timing for performance monitoring—but the function itself can’t be changed. Each decorator adds one layer of behavior. We’ll need to compose them correctly so that logging and timing both work together without interfering.
Goal
Create two decorators:
withLogging(fn): Logs input arguments and the returned value.withTiming(fn): Measures execution time and logs it.
Then, combine them in the same async function. The composed decorator should log arguments, output, and timing in the correct order.
Constraints
Do not modify the
fetchUserDatafunction.Both decorators must be independent and composable.
You must call
withTiming(withLogging(fetchUserData))to layer them.Do not use conditionals to merge behaviors.
If your [TIMER] log isn’t showing a function name, it’s because withLogging(fetchUserData) returns an anonymous wrapper function. When withTiming wraps it, the original name is lost. To fix this, use Object.defineProperty(wrappedFn, 'name', { value: fn.name }) to preserve the name for downstream decorators.
Sample output
The examples below illustrate what the output should look like:
const decoratedFetch = withTiming(withLogging(fetchUserData));(async () => {await decoratedFetch(101);})();/* Expected output (Timer may vary):[LOG] Called with args: [101][LOG] Returned: { id: 101, name: 'Alice' }[TIMER] fetchUserData took 121ms */
Good luck trying the problem! If you’re unsure how to proceed, check the “Solution” tab above.
Problem: Chain Multiple Decorators on a Service Method
Problem statement
You’re working with a simulated service that fetches user data asynchronously. The team wants to add logging for visibility and timing for performance monitoring—but the function itself can’t be changed. Each decorator adds one layer of behavior. We’ll need to compose them correctly so that logging and timing both work together without interfering.
Goal
Create two decorators:
withLogging(fn): Logs input arguments and the returned value.withTiming(fn): Measures execution time and logs it.
Then, combine them in the same async function. The composed decorator should log arguments, output, and timing in the correct order.
Constraints
Do not modify the
fetchUserDatafunction.Both decorators must be independent and composable.
You must call
withTiming(withLogging(fetchUserData))to layer them.Do not use conditionals to merge behaviors.
If your [TIMER] log isn’t showing a function name, it’s because withLogging(fetchUserData) returns an anonymous wrapper function. When withTiming wraps it, the original name is lost. To fix this, use Object.defineProperty(wrappedFn, 'name', { value: fn.name }) to preserve the name for downstream decorators.
Sample output
The examples below illustrate what the output should look like:
const decoratedFetch = withTiming(withLogging(fetchUserData));(async () => {await decoratedFetch(101);})();/* Expected output (Timer may vary):[LOG] Called with args: [101][LOG] Returned: { id: 101, name: 'Alice' }[TIMER] fetchUserData took 121ms */
Good luck trying the problem! If you’re unsure how to proceed, check the “Solution” tab above.