Lzh on GitHub

计算异步函数。

用法

import { computedAsync } from '@vueuse/core'
import { shallowRef } from 'vue'

const name = shallowRef('jack')

const userInfo = computedAsync(
  async () => {
    return await mockLookUp(name.value)
  },
  null, // 初始状态
)

计算状态

你需要传入一个 ref 来跟踪异步函数是否正在评估。

import { computedAsync } from '@vueuse/core'
import { shallowRef } from 'vue'

const evaluating = shallowRef(false)

const userInfo = computedAsync(
  async () => { /* 你的逻辑 */ },
  null,
  evaluating,
)

onCancel

当 computed 源在之前的异步函数解析完成之前发生变化时,你可能需要取消之前的异步函数。这里有一个示例展示了如何结合 fetch API 使用。

const packageName = shallowRef('@vueuse/core')

const downloads = computedAsync(async (onCancel) => {
  const abortController = new AbortController()
  
  onCancel(() => abortController.abort())
  
  return await fetch(
    `https://api.npmjs.org/downloads/point/last-week/${packageName.value}`,
    { signal: abortController.signal },
  )
    .then(response => response.ok ? response.json() : { downloads: '' })
    .then(result => result.downloads)
}, 0)

惰性

默认情况下,computedAsync 会在创建时立即开始解析,指定 lazy: true 会使其在第一次访问时才开始解析。

import { computedAsync } from '@vueuse/core'
import { shallowRef } from 'vue'

const evaluating = shallowRef(false)
const userInfo = computedAsync(
  async () => { /* 你的逻辑 */ },
  null,
  { lazy: true, evaluating },
)

注意事项

  • 就像 Vue 内置的 computed 函数一样,computedAsync 会进行依赖跟踪并在依赖变化时自动重新评估。但请注意,只有在第一个调用堆栈中引用的依赖才会被考虑在内。换句话说:异步访问的依赖不会触发异步计算值的重新评估
  • 与 Vue 内置的 computed 函数不同,异步计算值的重新评估会在依赖变化时触发,无论其结果当前是否被跟踪。

类型声明

/**
 * Handle overlapping async evaluations.
 *
 * @param cancelCallback The provided callback is invoked when a re-evaluation of the computed value is triggered before the previous one finished
 */
export type AsyncComputedOnCancel = (cancelCallback: Fn) => void
export interface AsyncComputedOptions<Lazy = boolean> {
  /**
   * Should value be evaluated lazily
   *
   * @default false
   */
  lazy?: Lazy
  /**
   * Ref passed to receive the updated of async evaluation
   */
  evaluating?: Ref<boolean>
  /**
   * Use shallowRef
   *
   * @default true
   */
  shallow?: boolean
  /**
   * The flush option allows for greater control over the timing of a history point, default to `pre`
   *
   * Possible values: `pre`, `post`, `sync`
   *
   * It works in the same way as the flush option in watch and watch effect in vue reactivity
   * @default 'pre'
   */
  flush?: "pre" | "post" | "sync"
  /**
   * Callback when error is caught.
   */
  onError?: (e: unknown) => void
}
/**
 * Create an asynchronous computed dependency.
 *
 * @see https://vueuse.org/computedAsync
 * @param evaluationCallback     The promise-returning callback which generates the computed value
 * @param initialState           The initial state, used until the first evaluation finishes
 * @param optionsOrRef           Additional options or a ref passed to receive the updates of the async evaluation
 */
export declare function computedAsync<T>(
  evaluationCallback: (onCancel: AsyncComputedOnCancel) => T | Promise<T>,
  initialState: T,
  optionsOrRef: AsyncComputedOptions<true>,
): ComputedRef<T>
export declare function computedAsync<T>(
  evaluationCallback: (onCancel: AsyncComputedOnCancel) => T | Promise<T>,
  initialState: undefined,
  optionsOrRef: AsyncComputedOptions<true>,
): ComputedRef<T | undefined>
export declare function computedAsync<T>(
  evaluationCallback: (onCancel: AsyncComputedOnCancel) => T | Promise<T>,
  initialState: T,
  optionsOrRef?: Ref<boolean> | AsyncComputedOptions,
): Ref<T>
export declare function computedAsync<T>(
  evaluationCallback: (onCancel: AsyncComputedOnCancel) => T | Promise<T>,
  initialState?: undefined,
  optionsOrRef?: Ref<boolean> | AsyncComputedOptions,
): Ref<T | undefined>
export { computedAsync as asyncComputed }