A Vue 3 composable for managing async task queues with reactive state, concurrency control, pause/resume, and retry support
npm install vue-reactive-queueReactive async task queue for Vue 3 with concurrency control.
- π Concurrency Control - Limit parallel task execution
- π Reactive State - Track task status in real-time with Vue reactivity
- βΈοΈ Pause/Resume - Control queue execution flow
- π Retry - Retry failed tasks with one call
- π Task History - Keep track of completed tasks
- π― Manual Execution - Start specific tasks on demand
- πͺ TypeScript - Full type support with generics
``bash`
npm install vue-reactive-queue
`ts
import { useQueue } from 'vue-reactive-queue'
const queue = useQueue()
// Add tasks to the queue
queue.add(async () => {
await processFile('document.pdf')
})
queue.add(async () => {
await processFile('image.png')
})
`
`ts
const queue = useQueue({ concurrency: 3 })
// Only 3 tasks will run in parallel
queue.add(() => fetchUser(1))
queue.add(() => fetchUser(2))
queue.add(() => fetchUser(3))
queue.add(() => fetchUser(4)) // waits for a slot
`
`vue
Pending: {{ queue.stats.value.pending }} Running: {{ queue.stats.value.running }} Completed: {{ queue.stats.value.completed }}
Task #{{ task.id }}: {{ task.status }}
`
`ts
const queue = useQueue()
queue.add(() => task1())
queue.add(() => task2())
queue.pause() // Stop executing new tasks
queue.resume() // Continue execution
`
`ts
const queue = useQueue({ immediate: false })
queue.add(() => task1())
queue.add(() => task2())
// Tasks are pending, not running
console.log(queue.stats.value.isPaused) // true
// Start when ready
queue.resume()
`
Start a specific task immediately, ignoring the pause state:
`ts
const queue = useQueue({ immediate: false })
const { id: idA } = queue.add(() => taskA())
const { id: idB } = queue.add(() => taskB())
const { id: idC } = queue.add(() => taskC())
// Only execute taskB, leave others pending
await queue.start(idB)
`
`ts
const queue = useQueue()
const { id } = queue.add(async () => {
await uploadFile(file) // might fail due to network issues
})
// Later, if the task failed
const result = queue.retry(id)
if (result.success) {
await result.promise
}
`
Attach custom data to tasks for UI rendering:
`ts
interface TaskMeta {
filename: string
size: number
}
const queue = useQueue
queue.add(
() => uploadFile(file),
{ filename: file.name, size: file.size }
)
`
`vue`
{{ task.meta?.filename }}
{{ task.status }}
`ts`
const queue = useQueue({
onSuccess(task) {
console.log('Task completed:', task.result)
},
onError(task, error) {
console.error('Task failed:', error)
},
onFinished() {
console.log('All tasks done!')
},
})
`ts
// Only keep the last 10 completed tasks
const queue = useQueue({ maxHistory: 10 })
// Keep no history (only pending/running tasks visible)
const queue = useQueue({ maxHistory: 0 })
`
`ts
const queue = useQueue()
queue.add(() => task1())
queue.add(() => task2())
queue.add(() => task3())
await queue.waitForIdle()
console.log('All tasks completed!')
`
`ts
import { ref } from 'vue'
const limit = ref(2)
const queue = useQueue({ concurrency: limit })
// Reactively update concurrency
limit.value = 5
// Or use setConcurrency
queue.setConcurrency(10)
`
`ts
export interface QueueTask
readonly id: number
status: 'pending' | 'running' | 'fulfilled' | 'rejected'
readonly createdAt: number
startedAt?: number
finishedAt?: number
result?: T
error?: unknown
readonly meta?: M
}
export interface QueueStats {
readonly pending: number
readonly running: number
readonly completed: number
readonly failed: number
readonly total: number
readonly isIdle: boolean
readonly isPaused: boolean
}
export interface UseQueueOptions
concurrency?: MaybeRefOrGetter
immediate?: boolean // default: true
maxHistory?: number // default: undefined (keep all)
onSuccess?: (task: QueueTask
onError?: (task: QueueTask
onFinished?: () => void
}
export interface UseQueueReturn
tasks: Readonly
stats: ComputedRef
concurrency: Readonly
add:
start: (id: number) => Promise
retry: (id: number) => RetryResult
remove: (id: number) => boolean
clear: () => void
pause: () => void
resume: () => void
setConcurrency: (value: number) => void
waitForIdle: () => Promise
}
``
MIT