React Interruption System: Graceful Task Cancellation
This challenge focuses on building a robust interruption system within a React application using TypeScript. You'll develop a mechanism to gracefully cancel ongoing asynchronous operations, such as API requests or long-running computations, triggered by user actions or application state changes. This is crucial for providing a responsive user experience, preventing race conditions, and managing resources efficiently.
Problem Description
Your task is to create a React component that manages and cancels asynchronous operations. This component should allow triggering multiple asynchronous tasks and provide a way to cancel any of them before they complete.
Key Requirements:
- Task Triggering: The component must have a mechanism to initiate multiple asynchronous tasks. For this challenge, these tasks will be simulated using
setTimeoutto mimic network latency or computation time. - Interruption Mechanism: A clear UI element (e.g., a button) must be provided to cancel a specific running task. The user should be able to identify which task they want to cancel.
- State Management: The component should maintain the state of each running task (e.g., "running," "completed," "cancelled").
- Graceful Cancellation: When a task is cancelled, it should stop its execution cleanly. This means any pending actions (like updating the UI with a result) should be prevented.
- TypeScript: The entire solution must be written in TypeScript, leveraging its type-safety features.
Expected Behavior:
- When a task is triggered, its status should be displayed as "running."
- If a task completes before being cancelled, its status should change to "completed," and a success message or placeholder result should be shown.
- If a task is cancelled, its status should change to "cancelled," and no further actions related to that task should occur.
- The UI should clearly indicate which tasks are running, completed, or cancelled.
Edge Cases to Consider:
- Cancelling a task that has already completed.
- Cancelling a task that is very close to completion.
- Triggering multiple tasks simultaneously.
Examples
Example 1:
- UI State:
- Task 1: Running (Cancel Button)
- Task 2: Running (Cancel Button)
- User Action: Clicks "Cancel" for Task 1.
- Expected UI State after cancellation:
- Task 1: Cancelled
- Task 2: Running (Cancel Button)
Example 2:
- UI State:
- Task 1: Running (Cancel Button)
- Simulated Event: Task 1 completes naturally after 2 seconds.
- Expected UI State after completion:
- Task 1: Completed (with a result)
Example 3:
- UI State:
- Task 1: Running (Cancel Button)
- User Action: Clicks "Cancel" for Task 1.
- Simulated Event: Task 1 finishes its asynchronous operation just before the cancellation logic fully executes.
- Expected UI State:
- Task 1: Cancelled (The completion logic should be prevented due to the cancellation).
Constraints
- The simulated asynchronous tasks will have random durations between 500ms and 3000ms.
- You should be able to trigger a maximum of 5 tasks concurrently.
- The component should be a functional React component using hooks.
- Use
AbortControlleror a similar pattern for managing cancellation.
Notes
- Consider how you will uniquely identify each task for cancellation.
- Think about the lifecycle of your asynchronous operations and how to hook into them for cancellation.
- The
AbortControllerprovides a standard way to signal abortion to asynchronous operations that support it. ForsetTimeout, you'll need to manage clearing the timeout yourself. - Your solution should demonstrate clear state updates and predictable behavior when tasks are interrupted.
- Focus on the core logic of triggering and cancelling tasks. Styling is secondary for this challenge.