Hone logo
Hone
Problems

Building a Microtask Queue in Vue.js

This challenge focuses on implementing a robust microtask queue within a Vue.js application using TypeScript. A microtask queue is crucial for managing asynchronous operations efficiently, ensuring that certain high-priority tasks are executed before the browser repaints or user interaction occurs. This is particularly useful for complex UI updates or background processing that shouldn't block the main thread.

Problem Description

Your task is to create a Vue.js component that acts as a microtask queue manager. This queue should allow you to add tasks (functions) that need to be executed. The core requirement is to process these tasks in a specific order:

  1. High-priority tasks: These should be executed as soon as possible, ideally before any other rendering or user interaction.
  2. Low-priority tasks: These should be executed after high-priority tasks but still be managed efficiently, potentially in batches.

The system should handle concurrent additions of tasks and ensure that tasks are not lost. You will need to define how tasks are added and processed, and how the queue's state is reflected in the Vue component's UI.

Key Requirements:

  • Task Prioritization: Implement a mechanism to differentiate between high-priority and low-priority tasks.
  • Execution Order: High-priority tasks must always execute before low-priority tasks. Within each priority level, tasks should execute in the order they were added.
  • Asynchronous Processing: Tasks should be processed asynchronously. For high-priority tasks, leverage Promise.resolve().then() or queueMicrotask() for immediate scheduling. For low-priority tasks, consider setTimeout(..., 0) or requestAnimationFrame for batching.
  • Vue Integration: The microtask queue should be managed within a Vue component (using the Composition API with TypeScript). The component should display the current number of pending high-priority and low-priority tasks.
  • Task Addition: Provide a user interface (e.g., buttons) to add both high-priority and low-priority tasks to the queue.
  • Task Execution Feedback: When a task is executed, simulate some work (e.g., increment a counter) and update the UI to reflect the completed task.

Expected Behavior:

When a user clicks buttons to add tasks:

  • The pending task counts in the UI should update immediately.
  • When the event loop is free, high-priority tasks should be processed one by one, updating the UI after each completion.
  • After all high-priority tasks are done, low-priority tasks should be processed, potentially in batches (e.g., processing a few at a time and then yielding if the queue is large).

Edge Cases:

  • Rapid addition of many tasks.
  • Tasks that themselves schedule more tasks.
  • Ensuring that even if tasks are added while processing is ongoing, they are correctly queued.

Examples

Example 1: Basic Task Addition and Processing

Initial State:
High-priority tasks pending: 0
Low-priority tasks pending: 0
Tasks completed: 0

User clicks "Add High-Priority Task" button twice.
User clicks "Add Low-Priority Task" button three times.

UI Updates:
High-priority tasks pending: 2
Low-priority tasks pending: 3
Tasks completed: 0

As the microtask queue processes:
(High-priority task 1 executes)
High-priority tasks pending: 1
Low-priority tasks pending: 3
Tasks completed: 1

(High-priority task 2 executes)
High-priority tasks pending: 0
Low-priority tasks pending: 3
Tasks completed: 2

(Low-priority task 1 executes)
High-priority tasks pending: 0
Low-priority tasks pending: 2
Tasks completed: 3

(Low-priority task 2 executes)
High-priority tasks pending: 0
Low-priority tasks pending: 1
Tasks completed: 4

(Low-priority task 3 executes)
High-priority tasks pending: 0
Low-priority tasks pending: 0
Tasks completed: 5

Example 2: Task Scheduling More Tasks

Initial State:
High-priority tasks pending: 0
Low-priority tasks pending: 0
Tasks completed: 0

User clicks "Add High-Priority Task" button.
This task is designed to add another high-priority task upon completion.

UI Updates:
High-priority tasks pending: 1
Low-priority tasks pending: 0
Tasks completed: 0

(High-priority task 1 executes)
  - Inside task 1, another high-priority task is scheduled.
High-priority tasks pending: 1 (the newly scheduled one)
Low-priority tasks pending: 0
Tasks completed: 1

(High-priority task 2 (scheduled by task 1) executes)
High-priority tasks pending: 0
Low-priority tasks pending: 0
Tasks completed: 2

Constraints

  • The Vue version used should be 3.x.
  • The solution must be implemented in TypeScript.
  • Avoid using external state management libraries like Pinia or Vuex for the core queue logic; manage it within the component's state.
  • The UI should be responsive, updating counts in near real-time.
  • For low-priority tasks, if the queue exceeds a certain threshold (e.g., 100 tasks), implement a simple batching mechanism (e.g., process 10 at a time and then yield).

Notes

  • Consider using ref for reactive state management in your Vue Composition API setup.
  • Think about how to handle errors within the queued tasks. For this challenge, you can opt to simply log errors and continue processing other tasks.
  • The primary goal is to demonstrate a clear understanding of microtask queuing principles within a Vue.js context. Experiment with different asynchronous scheduling methods (Promise.resolve().then, queueMicrotask, setTimeout, requestAnimationFrame) and their implications.
  • For low-priority tasks, setTimeout(..., 0) is a common approach to defer execution to the next event loop tick, allowing other synchronous code to run first. requestAnimationFrame is ideal for tasks that need to synchronize with browser repaints. Choose an appropriate method for your batching strategy.
Loading editor...
typescript