Skip to content

useFetch

类别
导出体积
2.42 kB
上次更改
2 minutes ago

响应式的 Fetch API 提供了中止请求、在请求发送之前拦截请求、在 URL 变化时自动重新获取请求,并创建具有预定义选项的自定义 useFetch 的功能。

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

TIP

在 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

使用方法

基本用法

只需提供一个 URL,即可使用 useFetch 函数。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 变化时重新获取

使用 ref 作为 URL 参数将允许 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' // 将触发另一个请求

阻止立即触发请求

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' // 修改响应数据

    return ctx
  },
})

onFetchError 选项可以在将 updateDataOnError 设置为 true 时拦截响应数据和错误,然后更新它们。

ts
const { data } = useFetch(url, {
  updateDataOnError: true,
  onFetchError(ctx) {
    // 5xx 响应时,ctx.data 可能为 null
    if (ctx.data === null)
      ctx.data = { title: 'Hunter x Hunter' } // 修改响应数据

    ctx.error = new Error('Custom Error') // 修改错误
    return ctx
  },
})

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

设置请求方法和返回类型

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

ts
// 使用 GET 方法发送请求,并将数据解析为 JSON
const { data } = useFetch(url).get().json()

// 使用 POST 方法发送请求,并将数据解析为文本
const { data } = useFetch(url).post().text()

// 或使用选项设置方法

// 使用 GET 方法发送请求,并将数据解析为 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 时,预配置实例中的 beforeFetch 将会运行
    async beforeFetch({ options }) {
      const myToken = await getMyToken()
      options.headers.Authorization = `Bearer ${myToken}`

      return { options }
    },
  },
})

// 使用预配置的 beforeFetch
const { isFetching, error, data } = useMyFetch('users')

// 使用自定义 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 将分别在 fetch 请求的响应和错误时触发。

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

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

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

类型声明

显示类型声明
typescript
export interface UseFetchReturn<T> {
  /**
   * 表示 fetch 请求是否已完成
   */
  isFinished: Readonly<Ref<boolean>>
  /**
   * HTTP fetch 响应的 statusCode
   */
  statusCode: Ref<number | null>
  /**
   * fetch 响应的原始数据
   */
  response: Ref<Response | null>
  /**
   * 可能发生的任何 fetch 错误
   */
  error: Ref<any>
  /**
   * 成功时的 fetch 响应体,可能是 JSON 或文本
   */
  data: Ref<T | null>
  /**
   * 表示当前是否正在进行 fetch 请求
   */
  isFetching: Readonly<Ref<boolean>>
  /**
   * 表示 fetch 请求是否可以中止
   */
  canAbort: ComputedRef<boolean>
  /**
   * 表示 fetch 请求是否已中止
   */
  aborted: Ref<boolean>
  /**
   * 中止 fetch 请求
   */
  abort: Fn
  /**
   * 手动调用 fetch
   * (默认不抛出错误)
   */
  execute: (throwOnFailed?: boolean) => Promise<any>
  /**
   * 在 fetch 请求完成后触发
   */
  onFetchResponse: EventHookOn<Response>
  /**
   * 在 fetch 请求错误后触发
   */
  onFetchError: EventHookOn
  /**
   * 在 fetch 完成后触发
   */
  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 {
  /**
   * 当前请求的计算后的 URL
   */
  url: string
  /**
   * 当前请求的请求选项
   */
  options: RequestInit
  /**
   * 取消当前请求
   */
  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 函数
   */
  fetch?: typeof window.fetch
  /**
   * 当 `useFetch` 被使用时是否自动运行 fetch
   *
   * @default true
   */
  immediate?: boolean
  /**
   * 当以下情况发生时是否自动重新获取:
   * - 如果 URL 是一个 ref,则 URL 被更改
   * - 如果 payload 是一个 ref,则 payload 被更改
   *
   * @default false
   */
  refetch?: MaybeRefOrGetter<boolean>
  /**
   * 请求完成之前的初始数据
   *
   * @default null
   */
  initialData?: any
  /**
   * 在多少毫秒后中止请求
   * `0` 表示使用浏览器默认值
   *
   * @default 0
   */
  timeout?: number
  /**
   * 允许在发生 fetch 错误时更新 `data` ref,无论是在提供的回调函数中还是在 `onFetchError` 回调中改变
   *
   * @default false
   */
  updateDataOnError?: boolean
  /**
   * 在 fetch 请求被分派之前立即运行
   */
  beforeFetch?: (
    ctx: BeforeFetchContext,
  ) =>
    | Promise<Partial<BeforeFetchContext> | void>
    | Partial<BeforeFetchContext>
    | void
  /**
   * 在 fetch 请求返回后立即运行。
   * 在任何 2xx 响应之后运行
   */
  afterFetch?: (
    ctx: AfterFetchContext,
  ) => Promise<Partial<AfterFetchContext>> | Partial<AfterFetchContext>
  /**
   * 在 fetch 请求返回后立即运行。
   * 在任何 4xx 和 5xx 响应之后运行
   */
  onFetchError?: (ctx: {
    data: any
    response: Response | null
    error: any
  }) => Promise<Partial<OnFetchErrorContext>> | Partial<OnFetchErrorContext>
}
export interface CreateFetchOptions {
  /**
   * 除非 URL 是绝对的,否则将添加到所有 URL 前面的基础 URL
   */
  baseUrl?: MaybeRefOrGetter<string>
  /**
   * 确定 beforeFetch、afterFetch、onFetchError 的继承行为
   * @default 'chain'
   */
  combination?: Combination
  /**
   * useFetch 函数的默认选项
   */
  options?: UseFetchOptions
  /**
   * fetch 请求的选项
   */
  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 on 2/20/2024
f5587 - fix: remove unnecessary spread operator in iterable conversion (#3660)
31d4a - fix: mark isFinished, isFetching readonly (#3616)
a086e - fix: stricter types
v10.7.0 on 12/5/2023
fccf2 - feat: upgrade deps (#3614)
8cbfd - fix: clone 'Response' on reading (#3607) (#3608)
3456d - fix: immediately modify the status after the request is completed (#3603)
v10.6.0 on 11/9/2023
75ca2 - fix: don't set isFetching to false when a request is aborted because of a refetch (#3479)
v10.4.0 on 8/25/2023
945ca - feat: introduce updateDataOnError option (#3092)
v10.3.0 on 7/30/2023
b7e3d - fix: generated payloadType on execute (#3251)
v10.1.1 on 5/1/2023
d051f - fix: combineCallbacks does not merge options (#3015)
v10.0.0-beta.4 on 4/13/2023
4d757 - feat(types)!: rename MaybeComputedRef to MaybeRefOrGetter
10e98 - feat(toRef)!: rename resolveRef to toRef
0a72b - feat(toValue): rename resolveUnref to toValue
v10.0.0-beta.0 on 3/14/2023
78cfb - feat: update data on success (#2711)
fff45 - fix: abort before updating state (#2805)
v9.13.0 on 2/18/2023
cd9d6 - feat: cancel previous request on refetch (#2750)
c2bc6 - fix: check if it's object for isFetchOptions
v9.9.0 on 12/23/2022
000fd - fix: doesn't work with formData payload (#2440)
v9.5.0 on 11/9/2022
934a8 - feat: support sending the custom request to an absolute URL regardless baseURL (#2210)
a8496 - feat: allow configure lifecycle handler behavior (#2333)
v9.3.1 on 10/17/2022
45750 - fix: fix incorrect chainCallbacks behavior (#2231)