Hone logo
Hone
Problems

Reactive Work Loop with Progress Tracking

This challenge asks you to implement a React component that manages a series of asynchronous tasks (represented as functions) and displays the progress of their execution. A "work loop" is a common pattern for orchestrating multiple operations, and this exercise will help you understand how to manage asynchronous operations and state updates effectively within a React application. This is useful for scenarios like data processing, API calls, or any sequential operation where you want to provide feedback to the user.

Problem Description

You need to create a WorkLoop component that accepts an array of workFunctions. Each workFunction is a function that returns a Promise. The WorkLoop component should:

  1. Execute the workFunctions sequentially: Each function should only start executing after the previous one has completed (resolved or rejected).
  2. Track and display progress: The component should maintain and display the current progress as a percentage (0-100). Update the progress after each work function completes.
  3. Handle errors: If any workFunction rejects, the component should stop the loop, display an error message, and prevent further execution.
  4. Display status messages: Show messages indicating the current status of the work loop (e.g., "Loading...", "Processing...", "Completed", "Error").
  5. Provide a "Start" button: The component should have a button that, when clicked, initiates the work loop. The button should be disabled until clicked.
  6. Provide a "Reset" button: The component should have a button that, when clicked, resets the component to its initial state (button enabled, progress 0, status "Loading...").

Expected Behavior:

  • Upon clicking "Start", the component should begin executing the workFunctions sequentially.
  • The progress bar should update after each function completes.
  • If a function rejects, the progress bar should stop updating, an error message should be displayed, and the "Start" button should remain disabled.
  • Upon clicking "Reset", the component should return to its initial state, allowing the user to restart the process.

Examples

Example 1:

Input: workFunctions = [() => new Promise<string>(resolve => setTimeout(() => resolve("Task 1 Complete"), 500)), () => new Promise<string>(resolve => setTimeout(() => resolve("Task 2 Complete"), 300)), () => new Promise<string>(resolve => setTimeout(() => resolve("Task 3 Complete"), 200))]
Output:  The component displays a progress bar that gradually fills up to 100% over approximately 1 second, with status messages like "Loading...", "Processing...", and finally "Completed".
Explanation: The work functions are executed sequentially, each taking a different amount of time. The progress bar reflects the completion of each task.

Example 2:

Input: workFunctions = [() => new Promise<string>(resolve => setTimeout(() => resolve("Task 1 Complete"), 500)), () => new Promise<string>((reject) => setTimeout(() => reject("Task 2 Failed"), 300)), () => new Promise<string>(resolve => setTimeout(() => resolve("Task 3 Complete"), 200))]
Output: The component displays a progress bar that fills up to approximately 50% (based on the completion of Task 1), then displays an error message "Task 2 Failed" and stops updating the progress bar. The "Start" button remains disabled.
Explanation: Task 2 rejects, causing the loop to terminate and display an error.

Example 3: (Empty workFunctions array)

Input: workFunctions = []
Output: The component displays the status message "Loading..." and the progress bar remains at 0%. The "Start" button is enabled.
Explanation:  Handles the edge case where no work functions are provided.

Constraints

  • workFunctions will be an array of functions, each returning a Promise.
  • Each Promise returned by a workFunction should resolve with a string or reject with a string.
  • The component should be implemented using functional components and React hooks.
  • The UI should be reasonably responsive; avoid blocking the main thread during Promise resolution.
  • The component should handle potential errors gracefully and prevent the application from crashing.

Notes

  • Consider using useState to manage the component's state (progress, status, error message, and button disabled state).
  • useEffect can be used to initiate the work loop when the "Start" button is clicked.
  • Use async/await to simplify the asynchronous logic within the work loop.
  • Think about how to handle the case where the workFunctions array is empty.
  • The progress calculation should be based on the number of completed tasks versus the total number of tasks. For example, if there are 3 tasks and 1 is complete, the progress should be approximately 33%.
  • Focus on clean, readable code and proper error handling.
Loading editor...
typescript