Lzh on GitHub

响应式异步状态。不会阻塞你的 setup 函数,并且会在 Promise 准备就绪后触发更改。state 默认为 shallowRef

Demo

<script setup lang="ts">
import { reactify, useAsyncState } from '@vueuse/core'
import axios from 'axios'
import YAML from 'yaml'

const stringify = reactify(
  (input: any) => YAML.stringify(input, (k, v) => {
    if (typeof v === 'function') {
      return undefined
    }
    return v
  }, {
    singleQuote: true,
    flowCollectionPadding: false,
  }),
)

const { isLoading, state, isReady, execute } = useAsyncState(
  (args) => {
    const id = args?.id || 1
    return axios.get(`https://jsonplaceholder.typicode.com/todos/${id}`).then(t => t.data)
  },
  {},
  {
    delay: 2000,
    resetOnExecute: false,
  },
)
</script>

<template>
  <div>
    <note>Ready: {{ isReady.toString() }}</note>
    <note>Loading: {{ isLoading.toString() }}</note>
    <pre lang="json" class="ml-2">{{ stringify(state) }}</pre>
    <button @click="() => execute(2000, { id: 2 })">
      Execute
    </button>
  </div>
</template>

使用

import { useAsyncState } from '@vueuse/core'
import axios from 'axios'

const { state, isReady, isLoading } = useAsyncState(
  axios
    .get('https://jsonplaceholder.typicode.com/todos/1')
    .then(t => t.data),
  { id: null },
)

手动触发异步函数

你也可以 手动触发 它。当你想要控制异步函数何时执行时,这会很有用。

<script setup lang="ts">
import { useAsyncState } from '@vueuse/core'

// useAsyncState:用于包装一个异步函数(action),并返回响应式状态。
// 初始状态值,组件加载时 state 的值为 ''
// { immediate: false }:表示不会在组件初始化时立即执行异步函数
// 返回的 state 是响应式的,可直接绑定到模板中
// 提供 isLoading、isReady、error 等状态,便于 UI 控制
const { state, execute, executeImmediate } = useAsyncState(action, '', { immediate: false })

// 一个异步函数,接受任意参数并返回 Promise。
async function action(event) {
  await new Promise(resolve => setTimeout(resolve, 500))
  return `${event.target.textContent} clicked!`
}
</script>

<template>
  <p>State: {{ state }}</p>

  <button class="button" @click="executeImmediate">
    Execute now
  </button>

  <button class="ml-2 button" @click="event => execute(500, event.target)">
    Execute with delay
  </button>
</template>

适用场景:

  • 按钮点击后请求数据:如提交表单、刷新数据、加载更多内容。
  • 用户输入后请求 API:如搜索框输入后请求搜索结果。
  • 延迟加载组件状态:避免组件初始化时不必要的请求。
  • 手动刷新机制:提供 “重试” 或 “刷新” 按钮功能。

类型声明

export interface UseAsyncStateReturnBase<
  Data,
  Params extends any[],
  Shallow extends boolean,
> {
  state: Shallow extends true ? Ref<Data> : Ref<UnwrapRef<Data>> // 响应式结果值(初始为 initialState,异步完成后更新)
  isReady: Ref<boolean> // 是否已完成
  isLoading: Ref<boolean> // 是否正在加载中
  error: Ref<unknown> // 异步执行出错时的错误对象
  execute: (delay?: number, ...args: Params) => Promise<Data> // 手动执行异步函数(支持延迟)
  executeImmediate: (...args: Params) => Promise<Data> // 不延迟立即执行
}

export type UseAsyncStateReturn<
  Data,
  Params extends any[],
  Shallow extends boolean,
> = UseAsyncStateReturnBase<Data, Params, Shallow> &
  PromiseLike<UseAsyncStateReturnBase<Data, Params, Shallow>>

export interface UseAsyncStateOptions<Shallow extends boolean, D = any> {
  /**
   * 当 "immediate" 为 true 时,promise 第一次执行的延迟时间(以毫秒为单位)。
   * 
   * @default 0
   */
  delay?: number
  /**
   * 在函数调用后立即执行 promise。
   * 如果设置了延迟,将会应用该延迟。

   * 当设置为 false 时,你需要手动执行它。
   *
   * @default true
   */
  immediate?: boolean
  /**
   * 捕获错误时的回调函数。
   */
  onError?: (e: unknown) => void
  /**
   * 成功回调
   * @param {D} data
   */
  onSuccess?: (data: D) => void
  /**
   * 是否在执行 promise 之前将 state 设置为 initialState。

   * 这在多次调用 execute 函数时(例如,用于刷新数据)会很有用。设置为 false 时,当前 state 保持不变,直到 promise 被解析。
   *
   * @default true
   */
  resetOnExecute?: boolean
  /**
   * 是否使用 shallowRef.
   *
   * @default true
   */
  shallow?: Shallow
  /**
   *
   * 是否在执行失败时抛出异常
   *
   * @default false
   */
  throwError?: boolean
}

/**
 * 响应式的异步状态。不会阻塞你的 setup 函数,并且在 promise 准备好后会触发变更。
 *
 * @see https://vueuse.org/useAsyncState
 * @param promise         The promise / async function to be resolved
 * @param initialState    The initial state, used until the first evaluation finishes
 * @param options
 */
export declare function useAsyncState<
  Data,
  Params extends any[] = any[],
  Shallow extends boolean = true,
>(
  promise: Promise<Data> | ((...args: Params) => Promise<Data>),
  initialState: Data,
  options?: UseAsyncStateOptions<Shallow, Data>,
): UseAsyncStateReturn<Data, Params, Shallow>