跳至内容

useFetch

类别
导出大小
2.42 kB
上次更改
上个月

响应式 Fetch API 提供了中止请求、在请求发出前拦截请求、在 URL 更改时自动重新获取请求以及使用预定义选项创建您自己的 useFetch 的能力。

通过 Vue School 的此免费视频课程学习 useFetch!

提示

在与 Nuxt 3 一起使用时,此函数将**不会**自动导入,以支持 Nuxt 自带的 useFetch()。如果要使用来自 VueUse 的函数,请使用显式导入。

演示

以下 URL 可用于测试 useFetch 的不同功能
普通请求: https://httpbin.org/get
中止请求: https://httpbin.org/delay/10
响应错误: http://httpbin.org/status/500
isFinished: false
isFetching: false
canAbort: false
statusCode: null
error: null
data: null

用法

基本用法

useFetch 函数只需提供一个 url 即可使用。url 可以是字符串或refdata 对象将包含请求的结果,error 对象将包含任何错误,isFetching 对象将指示请求是否正在加载。

ts
import { useFetch } from '@vueuse/core'

const { isFetching, error, data } = useFetch(url)

异步用法

useFetch 也可以像普通 fetch 一样等待。请注意,每当组件是异步时,使用它的任何组件都必须将组件包装在<Suspense>标签中。您可以在官方 Vue 3 文档中阅读更多关于 suspense api 的信息。

ts
import { useFetch } from '@vueuse/core'

const { isFetching, error, data } = await useFetch(url)

在 URL 更改时重新获取

对 url 参数使用ref将允许useFetch函数在 url 更改时自动触发另一个请求。

ts
const url = ref('https://my-api.com/user/1')

const { data } = useFetch(url, { refetch: true })

url.value = 'https://my-api.com/user/2' // Will trigger another request

防止请求立即发出

immediate选项设置为 false 将阻止请求发出,直到调用execute函数。

ts
const { execute } = useFetch(url, { immediate: false })

execute()

中止请求

可以使用useFetch函数中的abort函数中止请求。canAbort属性指示请求是否可以中止。

ts
const { abort, canAbort } = useFetch(url)

setTimeout(() => {
  if (canAbort.value)
    abort()
}, 100)

也可以通过使用timeout属性自动中止请求。当达到给定的超时时间时,它将调用abort函数。

ts
const { data } = useFetch(url, { timeout: 100 })

拦截请求

beforeFetch选项可以在发送请求之前拦截请求,并修改请求选项和URL。

ts
const { data } = useFetch(url, {
  async beforeFetch({ url, options, cancel }) {
    const myToken = await getMyToken()

    if (!myToken)
      cancel()

    options.headers = {
      ...options.headers,
      Authorization: `Bearer ${myToken}`,
    }

    return {
      options,
    }
  },
})

afterFetch选项可以在更新响应数据之前拦截响应数据。

ts
const { data } = useFetch(url, {
  afterFetch(ctx) {
    if (ctx.data.title === 'HxH')
      ctx.data.title = 'Hunter x Hunter' // Modifies the response data

    return ctx
  },
})

updateDataOnError设置为true时,onFetchError选项可以在更新响应数据和错误之前拦截响应数据和错误。

ts
const { data } = useFetch(url, {
  updateDataOnError: true,
  onFetchError(ctx) {
    // ctx.data can be null when 5xx response
    if (ctx.data === null)
      ctx.data = { title: 'Hunter x Hunter' } // Modifies the response data

    ctx.error = new Error('Custom Error') // Modifies the error
    return ctx
  },
})

console.log(data.value) // { title: 'Hunter x Hunter' }

设置请求方法和返回类型

可以通过在useFetch的末尾添加相应的方法来设置请求方法和返回类型。

ts
// Request will be sent with GET method and data will be parsed as JSON
const { data } = useFetch(url).get().json()

// Request will be sent with POST method and data will be parsed as text
const { data } = useFetch(url).post().text()

// Or set the method using the options

// Request will be sent with GET method and data will be parsed as blob
const { data } = useFetch(url, { method: 'GET' }, { refetch: true }).blob()

创建自定义实例

createFetch函数将返回一个useFetch函数,该函数具有提供给它的任何预配置选项。这对于与在整个应用程序中使用相同基本URL或需要授权标头的API交互非常有用。

ts
const useMyFetch = createFetch({
  baseUrl: 'https://my-api.com',
  options: {
    async beforeFetch({ options }) {
      const myToken = await getMyToken()
      options.headers.Authorization = `Bearer ${myToken}`

      return { options }
    },
  },
  fetchOptions: {
    mode: 'cors',
  },
})

const { isFetching, error, data } = useMyFetch('users')

如果要控制预配置实例和新生成的实例之间beforeFetchafterFetchonFetchError的行为。您可以提供一个combination选项在overwritechaining之间切换。

ts
const useMyFetch = createFetch({
  baseUrl: 'https://my-api.com',
  combination: 'overwrite',
  options: {
    // beforeFetch in pre-configured instance will only run when the newly spawned instance do not pass beforeFetch
    async beforeFetch({ options }) {
      const myToken = await getMyToken()
      options.headers.Authorization = `Bearer ${myToken}`

      return { options }
    },
  },
})

// use useMyFetch beforeFetch
const { isFetching, error, data } = useMyFetch('users')

// use custom beforeFetch
const { isFetching, error, data } = useMyFetch('users', {
  async beforeFetch({ url, options, cancel }) {
    const myToken = await getMyToken()

    if (!myToken)
      cancel()

    options.headers = {
      ...options.headers,
      Authorization: `Bearer ${myToken}`,
    }

    return {
      options,
    }
  },
})

事件

onFetchResponseonFetchError分别会在获取请求响应和错误时触发。

ts
const { onFetchResponse, onFetchError } = useFetch(url)

onFetchResponse((response) => {
  console.log(response.status)
})

onFetchError((error) => {
  console.error(error.message)
})

类型声明

显示类型声明
typescript
export interface UseFetchReturn<T> {
  /**
   * Indicates if the fetch request has finished
   */
  isFinished: Readonly<Ref<boolean>>
  /**
   * The statusCode of the HTTP fetch response
   */
  statusCode: Ref<number | null>
  /**
   * The raw response of the fetch response
   */
  response: Ref<Response | null>
  /**
   * Any fetch errors that may have occurred
   */
  error: Ref<any>
  /**
   * The fetch response body on success, may either be JSON or text
   */
  data: Ref<T | null>
  /**
   * Indicates if the request is currently being fetched.
   */
  isFetching: Readonly<Ref<boolean>>
  /**
   * Indicates if the fetch request is able to be aborted
   */
  canAbort: ComputedRef<boolean>
  /**
   * Indicates if the fetch request was aborted
   */
  aborted: Ref<boolean>
  /**
   * Abort the fetch request
   */
  abort: Fn
  /**
   * Manually call the fetch
   * (default not throwing error)
   */
  execute: (throwOnFailed?: boolean) => Promise<any>
  /**
   * Fires after the fetch request has finished
   */
  onFetchResponse: EventHookOn<Response>
  /**
   * Fires after a fetch request error
   */
  onFetchError: EventHookOn
  /**
   * Fires after a fetch has completed
   */
  onFetchFinally: EventHookOn
  get: () => UseFetchReturn<T> & PromiseLike<UseFetchReturn<T>>
  post: (
    payload?: MaybeRefOrGetter<unknown>,
    type?: string,
  ) => UseFetchReturn<T> & PromiseLike<UseFetchReturn<T>>
  put: (
    payload?: MaybeRefOrGetter<unknown>,
    type?: string,
  ) => UseFetchReturn<T> & PromiseLike<UseFetchReturn<T>>
  delete: (
    payload?: MaybeRefOrGetter<unknown>,
    type?: string,
  ) => UseFetchReturn<T> & PromiseLike<UseFetchReturn<T>>
  patch: (
    payload?: MaybeRefOrGetter<unknown>,
    type?: string,
  ) => UseFetchReturn<T> & PromiseLike<UseFetchReturn<T>>
  head: (
    payload?: MaybeRefOrGetter<unknown>,
    type?: string,
  ) => UseFetchReturn<T> & PromiseLike<UseFetchReturn<T>>
  options: (
    payload?: MaybeRefOrGetter<unknown>,
    type?: string,
  ) => UseFetchReturn<T> & PromiseLike<UseFetchReturn<T>>
  json: <JSON = any>() => UseFetchReturn<JSON> &
    PromiseLike<UseFetchReturn<JSON>>
  text: () => UseFetchReturn<string> & PromiseLike<UseFetchReturn<string>>
  blob: () => UseFetchReturn<Blob> & PromiseLike<UseFetchReturn<Blob>>
  arrayBuffer: () => UseFetchReturn<ArrayBuffer> &
    PromiseLike<UseFetchReturn<ArrayBuffer>>
  formData: () => UseFetchReturn<FormData> &
    PromiseLike<UseFetchReturn<FormData>>
}
type Combination = "overwrite" | "chain"
export interface BeforeFetchContext {
  /**
   * The computed url of the current request
   */
  url: string
  /**
   * The request options of the current request
   */
  options: RequestInit
  /**
   * Cancels the current request
   */
  cancel: Fn
}
export interface AfterFetchContext<T = any> {
  response: Response
  data: T | null
}
export interface OnFetchErrorContext<T = any, E = any> {
  error: E
  data: T | null
}
export interface UseFetchOptions {
  /**
   * Fetch function
   */
  fetch?: typeof window.fetch
  /**
   * Will automatically run fetch when `useFetch` is used
   *
   * @default true
   */
  immediate?: boolean
  /**
   * Will automatically refetch when:
   * - the URL is changed if the URL is a ref
   * - the payload is changed if the payload is a ref
   *
   * @default false
   */
  refetch?: MaybeRefOrGetter<boolean>
  /**
   * Initial data before the request finished
   *
   * @default null
   */
  initialData?: any
  /**
   * Timeout for abort request after number of millisecond
   * `0` means use browser default
   *
   * @default 0
   */
  timeout?: number
  /**
   * Allow update the `data` ref when fetch error whenever provided, or mutated in the `onFetchError` callback
   *
   * @default false
   */
  updateDataOnError?: boolean
  /**
   * Will run immediately before the fetch request is dispatched
   */
  beforeFetch?: (
    ctx: BeforeFetchContext,
  ) =>
    | Promise<Partial<BeforeFetchContext> | void>
    | Partial<BeforeFetchContext>
    | void
  /**
   * Will run immediately after the fetch request is returned.
   * Runs after any 2xx response
   */
  afterFetch?: (
    ctx: AfterFetchContext,
  ) => Promise<Partial<AfterFetchContext>> | Partial<AfterFetchContext>
  /**
   * Will run immediately after the fetch request is returned.
   * Runs after any 4xx and 5xx response
   */
  onFetchError?: (ctx: {
    data: any
    response: Response | null
    error: any
  }) => Promise<Partial<OnFetchErrorContext>> | Partial<OnFetchErrorContext>
}
export interface CreateFetchOptions {
  /**
   * The base URL that will be prefixed to all urls unless urls are absolute
   */
  baseUrl?: MaybeRefOrGetter<string>
  /**
   * Determine the inherit behavior for beforeFetch, afterFetch, onFetchError
   * @default 'chain'
   */
  combination?: Combination
  /**
   * Default Options for the useFetch function
   */
  options?: UseFetchOptions
  /**
   * Options for the fetch request
   */
  fetchOptions?: RequestInit
}
export declare function createFetch(
  config?: CreateFetchOptions,
): typeof useFetch
export declare function useFetch<T>(
  url: MaybeRefOrGetter<string>,
): UseFetchReturn<T> & PromiseLike<UseFetchReturn<T>>
export declare function useFetch<T>(
  url: MaybeRefOrGetter<string>,
  useFetchOptions: UseFetchOptions,
): UseFetchReturn<T> & PromiseLike<UseFetchReturn<T>>
export declare function useFetch<T>(
  url: MaybeRefOrGetter<string>,
  options: RequestInit,
  useFetchOptions?: UseFetchOptions,
): UseFetchReturn<T> & PromiseLike<UseFetchReturn<T>>

源代码

源代码演示文档

贡献者

Anthony Fu
wheat
Jelf
Ismail Gjevori
Anthony Fu
丶远方
qiang
KaKa
Toby Zerner
Jay214
webfansplz
陪我去看海吧
Pouya Mohammadkhani
BaboonKing
LJFloor
mymx2
Arthur Machado
Martijn Weghorst
KaKa
RAX7
Przemek Brzosko
abitwhy
sun0day
Young
sun0day
Curt Grimes
Yvan Zhu
ice
Antonio Román
Glandos
unknown_
btea
Shinigami
KaKa
Arda Soytürk

更新日志

v10.8.0 于 2024年2月20日
f5587 - 修复: 删除迭代转换中不必要的扩展运算符 (#3660)
31d4a - 修复: 将 isFinishedisFetching 标记为只读 (#3616)
a086e - 修复: 更严格的类型
v10.7.0 于 2023年12月5日
fccf2 - 特性: 升级依赖项 (#3614)
8cbfd - 修复: 在读取时克隆 'Response' (#3607) (#3608)
3456d - 修复: 请求完成后立即修改状态 (#3603)
v10.6.0 于 2023年11月9日
75ca2 - 修复: 由于重新获取而中止请求时,不要将 isFetching 设置为 false (#3479)
v10.4.0 于 2023年8月25日
945ca - 特性: 引入 updateDataOnError 选项 (#3092)
v10.3.0 于 2023年7月30日
b7e3d - 修复: 在执行时生成 payloadType (#3251)
v10.1.1 于 2023年5月1日
d051f - 修复: combineCallbacks 不合并选项 (#3015)
v10.0.0-beta.4 于 2023年4月13日
4d757 - 特性(类型)!: 将 MaybeComputedRef 重命名为 MaybeRefOrGetter
10e98 - 特性(toRef)!: 将 resolveRef 重命名为 toRef
0a72b - 特性(toValue): 将 resolveUnref 重命名为 toValue
v10.0.0-beta.0 于 2023年3月14日
78cfb - 特性: 在成功时更新数据 (#2711)
fff45 - 修复: 在更新状态之前中止 (#2805)
v9.13.0 于 2023年2月18日
cd9d6 - 特性: 在重新获取时取消先前的请求 (#2750)
c2bc6 - 修复: 检查 isFetchOptions 是否为对象
v9.9.0 于 2022年12月23日
000fd - 修复: 不适用于 formData 负载 (#2440)
v9.5.0 于 2022年11月9日
934a8 - 特性: 支持将自定义请求发送到绝对 URL,而不管 baseURL (#2210)
a8496 - 特性: 允许配置生命周期处理程序行为 (#2333)
v9.3.1 于 2022年10月17日
45750 - 修复: 修复不正确的 chainCallbacks 行为 (#2231)

在 MIT 许可证下发布。