Vize

use-async-queue

Run async tasks one after another, each receiving the previous result.

Package @vizejs/composable/use-async-queue
Own the source vize lib pull composable:use-async-queue
Runtime exports useAsyncQueue
Gzip budget 1280 B

Minimal setup

Use a Vue 3.5+ project with Vue SFC compilation configured (see Vite+ integration).

vp install @vizejs/composable

Import the entry directly. Call lifecycle-bound utilities inside <script setup> so cleanup follows the component scope; consult the runtime contract for this entry's SSR and hydration behavior.

import { useAsyncQueue } from "@vizejs/composable/use-async-queue";

Try it

Run dependent steps in order

Run async steps one after another, passing each result to the next, and show the state of every step.

Open the interactive example

What to observe: Run steps moves each step from pending to fulfilled in order and ends with Uploaded photo.jpg resized to 1200 px.

Pass immediate: false to start with run(). With interrupt: true (the default) a failing step marks the rest as aborted.

Compare the initial and interacted states
Run dependent steps in order: initial state
Initial state
Run dependent steps in order: state after the verified interactions
After the verified interactions

Copy the example

Save this complete SFC in your Vue project. Its public imports and source are the same ones executed in the preview.

<script setup lang="ts">
import { computed } from "vue";
import { useAsyncQueue } from "@vizejs/composable/use-async-queue";

const { results, activeIndex, isFinished, run } = useAsyncQueue(
  [
    () => "photo.jpg",
    (file: string) => `${file} resized to 1200 px`,
    (resized: string) => `Uploaded ${resized}`,
  ],
  { immediate: false },
);
const steps = ["Pick a photo", "Resize it", "Upload it"];
const summary = computed(() =>
  isFinished.value ? String(results.value[2]?.data) : `Step ${activeIndex.value + 1} of 3`,
);
</script>

<template>
  <div class="composable-example">
    <p>Run dependent steps in order, passing each result to the next step.</p>
    <button type="button" @click="() => run()">Run steps</button>
    <ol aria-label="Steps">
      <li v-for="(step, index) in steps" :key="step">{{ step }}: {{ results[index]?.state }}</li>
    </ol>
    <output aria-live="polite">{{ summary }}</output>
  </div>
</template>

Runtime contract

Utility Category Stability SSR Hydration Cleanup Targets Host globals Uses
useAsyncQueue async experimental safe stable returned-value web, server, worker, native, desktop, terminal AbortController —

API

useAsyncQueue

Run async tasks one after another, each receiving the previous result. Result types are inferred per position from the task tuple, and each task's previous parameter is contextually typed as the preceding task's result (up to six tasks; longer queues use the mapped-tuple signature with annotated parameters). Every task gets an AbortSignal; abort() (or the external signal) stops the queue and marks unfinished tasks "aborted". A new run() aborts the one in flight. Starts on the server too when immediate, but nothing awaits it there, so markup shows the pending state on both sides.

function useAsyncQueue<R1>( tasks: readonly [AsyncQueueTask<undefined, R1>], options?: UseAsyncQueueOptions, ): AsyncQueue<[R1]>
const { results } = useAsyncQueue([
  async () => fetchUser(),
  async (user) => fetchOrders(user.id),
]);

useAsyncQueue

function useAsyncQueue<R1, R2>( tasks: readonly [AsyncQueueTask<undefined, R1>, AsyncQueueTask<R1, R2>], options?: UseAsyncQueueOptions, ): AsyncQueue<[R1, R2]>

useAsyncQueue

function useAsyncQueue<R1, R2, R3>( tasks: readonly [AsyncQueueTask<undefined, R1>, AsyncQueueTask<R1, R2>, AsyncQueueTask<R2, R3>], options?: UseAsyncQueueOptions, ): AsyncQueue<[R1, R2, R3]>

useAsyncQueue

function useAsyncQueue<R1, R2, R3, R4>( tasks: readonly [ AsyncQueueTask<undefined, R1>, AsyncQueueTask<R1, R2>, AsyncQueueTask<R2, R3>, AsyncQueueTask<R3, R4>, ], options?: UseAsyncQueueOptions, ): AsyncQueue<[R1, R2, R3, R4]>

useAsyncQueue

function useAsyncQueue<R1, R2, R3, R4, R5>( tasks: readonly [ AsyncQueueTask<undefined, R1>, AsyncQueueTask<R1, R2>, AsyncQueueTask<R2, R3>, AsyncQueueTask<R3, R4>, AsyncQueueTask<R4, R5>, ], options?: UseAsyncQueueOptions, ): AsyncQueue<[R1, R2, R3, R4, R5]>

useAsyncQueue

function useAsyncQueue<R1, R2, R3, R4, R5, R6>( tasks: readonly [ AsyncQueueTask<undefined, R1>, AsyncQueueTask<R1, R2>, AsyncQueueTask<R2, R3>, AsyncQueueTask<R3, R4>, AsyncQueueTask<R4, R5>, AsyncQueueTask<R5, R6>, ], options?: UseAsyncQueueOptions, ): AsyncQueue<[R1, R2, R3, R4, R5, R6]>

useAsyncQueue

function useAsyncQueue<Results extends readonly unknown[]>( tasks: AsyncQueueTasks<Results>, options?: UseAsyncQueueOptions, ): AsyncQueue<Results>

useAsyncQueue

function useAsyncQueue( tasks: readonly ErasedTask[], options: UseAsyncQueueOptions = {}, ): AsyncQueue<readonly unknown[]>

Types

AsyncQueueTaskResult

Outcome record of one queued task.

Member Type Description
state AsyncQueueTaskState Current lifecycle state.
data Data | undefined Resolved value once fulfilled.
error unknown Failure once rejected.

AsyncQueueContext

Context passed to every queued task.

Member Type Description
signal AbortSignal Aborted when the queue is aborted.

UseAsyncQueueOptions

Options for useAsyncQueue.

Member Type Description
interrupt? boolean Stop at the first rejection (remaining tasks become "aborted").
immediate? boolean Start running right away.
signal? AbortSignal External cancellation; aborting it aborts the queue.
onError? (error: unknown, index: number) => void Called when a task rejects.
onFinished? () => void Called once the queue settles.

AsyncQueue

Queue state and controls returned by useAsyncQueue.

Member Type Description
activeIndex Readonly<ShallowRef<number>> Index of the running task (-1 before start, length when done).
results Readonly< ShallowRef<{ readonly [Index in keyof Results]: AsyncQueueTaskResult<Results[Index]> }> > Per-task outcome records, typed per position.
isFinished ComputedRef<boolean> Whether the queue settled (all done, interrupted, or aborted).
run () => Promise<{ readonly [Index in keyof Results]: AsyncQueueTaskResult<Results[Index]>; }> Run the queue (again) from the first task.
abort (reason?: unknown) => void Abort the running queue.