⬅️ Back to Table of Contents
📄 index.ts
📊 Analysis Summary
Metric |
Count |
🔧 Functions |
3 |
📦 Imports |
4 |
📊 Variables & Constants |
3 |
⚡ Async/Await Patterns |
2 |
🟢 Vue Composition API |
1 |
📐 Interfaces |
3 |
📑 Type Aliases |
2 |
📚 Table of Contents
🛠️ File Location:
📂 packages/core/useAsyncQueue/index.ts
📦 Imports
Name |
Source |
ShallowRef |
vue |
noop |
@vueuse/shared |
reactive |
vue |
shallowRef |
vue |
Variables & Constants
Name |
Type |
Kind |
Value |
Exported |
promiseState |
`Record< |
|
|
|
UseAsyncQueueResult['state'], |
|
|
|
|
UseAsyncQueueResult['state'] |
|
|
|
|
>| const | { |
|
|
|
|
aborted: 'aborted', |
|
|
|
|
fulfilled: 'fulfilled', |
|
|
|
|
pending: 'pending', |
|
|
|
|
rejected: 'rejected', |
|
|
|
|
}` |
✗ |
|
|
|
result |
{ [P in keyof T]: UseAsyncQueueResult<T[P]>; } |
const |
reactive(initialResult) as { [P in keyof T]: UseAsyncQueueResult<T[P]> } |
✗ |
error |
Error |
const |
new Error('aborted') |
✗ |
Async/Await Patterns
Type |
Function |
Await Expressions |
Promise Chains |
promise-chain |
useAsyncQueue |
none |
prev |
.then((prevRes) => { |
|
|
|
if (signal?.aborted) { |
|
|
|
updateResult(promiseState.aborted, new Error('aborted')) |
|
|
|
return |
|
|
|
} |
|
|
|
if (
result[activeIndex.value]?.state === promiseState.rejected
&& interrupt
) {
onFinished()
return
}
const done = curr(prevRes).then((currentRes: any) => {
updateResult(promiseState.fulfilled, currentRes)
if (activeIndex.value === tasks.length - 1)
onFinished()
return currentRes
})
if (!signal)
return done
return Promise.race([done, whenAborted(signal)])
}).catch, prev.then, curr(prevRes).then, Promise.race, Promise.resolve |
| promise-chain | whenAborted
| none | new Promise(...) |
Vue Composition API
Name |
Type |
Reactive Variables |
Composables |
reactive |
reactive |
none |
none |
Functions
useAsyncQueue(tasks: S & Array<UseAsyncQueueTask<any>>, options: UseAsyncQueueOptions): UseAsyncQueueReturn<{ [P in keyof T]: UseAsyncQueueResult<T[P]> }>
Code
export function useAsyncQueue<T extends any[], S = MapQueueTask<T>>(
tasks: S & Array<UseAsyncQueueTask<any>>,
options?: UseAsyncQueueOptions,
): UseAsyncQueueReturn<{ [P in keyof T]: UseAsyncQueueResult<T[P]> }> {
const {
interrupt = true,
onError = noop,
onFinished = noop,
signal,
} = options || {}
const promiseState: Record<
UseAsyncQueueResult<T>['state'],
UseAsyncQueueResult<T>['state']
> = {
aborted: 'aborted',
fulfilled: 'fulfilled',
pending: 'pending',
rejected: 'rejected',
}
const initialResult = Array.from(Array.from({ length: tasks.length }), () => ({ state: promiseState.pending, data: null }))
const result = reactive(initialResult) as { [P in keyof T]: UseAsyncQueueResult<T[P]> }
const activeIndex = shallowRef<number>(-1)
if (!tasks || tasks.length === 0) {
onFinished()
return {
activeIndex,
result,
}
}
function updateResult(state: UseAsyncQueueResult<T>['state'], res: unknown) {
activeIndex.value++
result[activeIndex.value].data = res as T
result[activeIndex.value].state = state
}
tasks.reduce((prev, curr) => {
return prev
.then((prevRes) => {
if (signal?.aborted) {
updateResult(promiseState.aborted, new Error('aborted'))
return
}
if (
result[activeIndex.value]?.state === promiseState.rejected
&& interrupt
) {
onFinished()
return
}
const done = curr(prevRes).then((currentRes: any) => {
updateResult(promiseState.fulfilled, currentRes)
if (activeIndex.value === tasks.length - 1)
onFinished()
return currentRes
})
if (!signal)
return done
return Promise.race([done, whenAborted(signal)])
})
.catch((e) => {
if (signal?.aborted) {
updateResult(promiseState.aborted, e)
return e
}
updateResult(promiseState.rejected, e)
onError()
return e
})
}, Promise.resolve())
return {
activeIndex,
result,
}
}
Code
function updateResult(state: UseAsyncQueueResult<T>['state'], res: unknown) {
activeIndex.value++
result[activeIndex.value].data = res as T
result[activeIndex.value].state = state
}
- Parameters:
state: UseAsyncQueueResult<T>['state']
res: unknown
- Return Type:
void
whenAborted(signal: AbortSignal): Promise<never>
Code
function whenAborted(signal: AbortSignal): Promise<never> {
return new Promise((resolve, reject) => {
const error = new Error('aborted')
if (signal.aborted)
reject(error)
else
signal.addEventListener('abort', () => reject(error), { once: true })
})
}
- Parameters:
signal: AbortSignal
- Return Type:
Promise<never>
- Calls:
reject
signal.addEventListener
Interfaces
UseAsyncQueueResult<T>
Interface Code
export interface UseAsyncQueueResult<T> {
state: 'aborted' | 'fulfilled' | 'pending' | 'rejected'
data: T | null
}
Properties
Name |
Type |
Optional |
Description |
state |
'aborted' | 'fulfilled' | 'pending' | 'rejected' |
✗ |
|
data |
T | null |
✗ |
|
UseAsyncQueueReturn<T>
Interface Code
export interface UseAsyncQueueReturn<T> {
activeIndex: ShallowRef<number>
result: T
}
Properties
Name |
Type |
Optional |
Description |
activeIndex |
ShallowRef<number> |
✗ |
|
result |
T |
✗ |
|
UseAsyncQueueOptions
Interface Code
export interface UseAsyncQueueOptions {
/**
* Interrupt tasks when current task fails.
*
* @default true
*/
interrupt?: boolean
/**
* Trigger it when the tasks fails.
*
*/
onError?: () => void
/**
* Trigger it when the tasks ends.
*
*/
onFinished?: () => void
/**
* A AbortSignal that can be used to abort the task.
*/
signal?: AbortSignal
}
Properties
Name |
Type |
Optional |
Description |
interrupt |
boolean |
✓ |
|
onError |
() => void |
✓ |
|
onFinished |
() => void |
✓ |
|
signal |
AbortSignal |
✓ |
|
Type Aliases
UseAsyncQueueTask<T>
type UseAsyncQueueTask<T> = (...args: any[]) => T | Promise<T>;
MapQueueTask<T extends any[] extends any[]>
type MapQueueTask<T extends any[] extends any[]> = {
[K in keyof T]: UseAsyncQueueTask<T[K]>
};