useFetch
響應式 Fetch API 提供了中止請求、在請求發送前攔截請求、在 URL 變更時自動重新獲取請求,以及使用預定義選項建立您自己的 useFetch
的能力。
提示
當與 Nuxt 3 一起使用時,此函式將不會自動導入,而是優先使用 Nuxt 的內建 useFetch()
。如果您想使用 VueUse 的函式,請使用明確導入。
示範
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 可以是字串或 ref
。data
物件將包含請求的結果,error
物件將包含任何錯誤,而 isFetching
物件將指示請求是否正在加載。
import { useFetch } from '@vueuse/core'
const { isFetching, error, data } = useFetch(url)
非同步用法
useFetch
也可以像一般的 fetch 一樣被 await。請注意,只要元件是非同步的,任何使用它的元件都必須將該元件包裹在 <Suspense>
標籤中。您可以在 官方 Vue 3 文件中閱讀更多關於 suspense api 的資訊
import { useFetch } from '@vueuse/core'
const { isFetching, error, data } = await useFetch(url)
URL 變更時重新獲取
使用 ref
作為 url 參數將允許 useFetch
函式在 URL 變更時自動觸發另一個請求。
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
函式之前發送。
const { execute } = useFetch(url, { immediate: false })
execute()
中止請求
可以使用 useFetch
函式的 abort
函式來中止請求。canAbort
屬性指示請求是否可以中止。
const { abort, canAbort } = useFetch(url)
setTimeout(() => {
if (canAbort.value)
abort()
}, 100)
也可以使用 timeout
屬性自動中止請求。當達到給定的 timeout 時,它將呼叫 abort
函式。
const { data } = useFetch(url, { timeout: 100 })
攔截請求
beforeFetch
選項可以在請求發送之前攔截請求,並修改請求選項和 URL。
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
選項可以在回應資料更新之前攔截回應資料。
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
選項可以在回應資料和錯誤更新之前攔截它們。
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
的末尾來設定請求方法和回傳類型
// 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 互動非常有用。
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')
如果您想控制預先配置的實例和新產生的實例之間的 beforeFetch
、afterFetch
、onFetchError
的行為。您可以提供 combination
選項來在 overwrite
或 chaining
之間切換。
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,
}
},
})
您可以透過在 afterFetch
或 onFetchError
中呼叫 execute
方法來重新執行請求。以下是一個簡單的刷新令牌範例
let isRefreshing = false
const refreshSubscribers: Array<() => void> = []
const useMyFetch = createFetch({
baseUrl: 'https://my-api.com',
options: {
async beforeFetch({ options }) {
const myToken = await getMyToken()
options.headers.Authorization = `Bearer ${myToken}`
return { options }
},
afterFetch({ data, response, context, execute }) {
if (needRefreshToken) {
if (!isRefreshing) {
isRefreshing = true
refreshToken().then((newToken) => {
if (newToken.value) {
isRefreshing = false
setMyToken(newToken.value)
onRrefreshed()
}
else {
refreshSubscribers.length = 0
// handle refresh token error
}
})
}
return new Promise((resolve) => {
addRefreshSubscriber(() => {
execute().then((response) => {
resolve({ data, response })
})
})
})
}
return { data, response }
},
// or use onFetchError with updateDataOnError
updateDataOnError: true,
onFetchError({ error, data, response, context, execute }) {
// same as afterFetch
return { error, data }
},
},
fetchOptions: {
mode: 'cors',
},
})
async function refreshToken() {
const { data, execute } = useFetch<string>('refresh-token', {
immediate: false,
})
await execute()
return data
}
function onRrefreshed() {
refreshSubscribers.forEach(callback => callback())
refreshSubscribers.length = 0
}
function addRefreshSubscriber(callback: () => void) {
refreshSubscribers.push(callback)
}
const { isFetching, error, data } = useMyFetch('users')
let isRefreshing = false
const refreshSubscribers = []
const useMyFetch = createFetch({
baseUrl: 'https://my-api.com',
options: {
async beforeFetch({ options }) {
const myToken = await getMyToken()
options.headers.Authorization = `Bearer ${myToken}`
return { options }
},
afterFetch({ data, response, context, execute }) {
if (needRefreshToken) {
if (!isRefreshing) {
isRefreshing = true
refreshToken().then((newToken) => {
if (newToken.value) {
isRefreshing = false
setMyToken(newToken.value)
onRrefreshed()
} else {
refreshSubscribers.length = 0
// handle refresh token error
}
})
}
return new Promise((resolve) => {
addRefreshSubscriber(() => {
execute().then((response) => {
resolve({ data, response })
})
})
})
}
return { data, response }
},
// or use onFetchError with updateDataOnError
updateDataOnError: true,
onFetchError({ error, data, response, context, execute }) {
// same as afterFetch
return { error, data }
},
},
fetchOptions: {
mode: 'cors',
},
})
async function refreshToken() {
const { data, execute } = useFetch('refresh-token', {
immediate: false,
})
await execute()
return data
}
function onRrefreshed() {
refreshSubscribers.forEach((callback) => callback())
refreshSubscribers.length = 0
}
function addRefreshSubscriber(callback) {
refreshSubscribers.push(callback)
}
const { isFetching, error, data } = useMyFetch('users')
事件
onFetchResponse
和 onFetchError
將分別在 fetch 請求回應和錯誤時觸發。
const { onFetchResponse, onFetchError } = useFetch(url)
onFetchResponse((response) => {
console.log(response.status)
})
onFetchError((error) => {
console.error(error.message)
})
類型宣告
顯示類型宣告
export interface UseFetchReturn<T> {
/**
* Indicates if the fetch request has finished
*/
isFinished: Readonly<ShallowRef<boolean>>
/**
* The statusCode of the HTTP fetch response
*/
statusCode: ShallowRef<number | null>
/**
* The raw response of the fetch response
*/
response: ShallowRef<Response | null>
/**
* Any fetch errors that may have occurred
*/
error: ShallowRef<any>
/**
* The fetch response body on success, may either be JSON or text
*/
data: ShallowRef<T | null>
/**
* Indicates if the request is currently being fetched.
*/
isFetching: Readonly<ShallowRef<boolean>>
/**
* Indicates if the fetch request is able to be aborted
*/
canAbort: ComputedRef<boolean>
/**
* Indicates if the fetch request was aborted
*/
aborted: ShallowRef<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
context: BeforeFetchContext
execute: (throwOnFailed?: boolean) => Promise<any>
}
export interface OnFetchErrorContext<T = any, E = any> {
error: E
data: T | null
response: Response | null
context: BeforeFetchContext
execute: (throwOnFailed?: boolean) => Promise<any>
}
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: OnFetchErrorContext,
) => 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>>
來源
貢獻者
更新日誌
v12.8.0
於 2025/3/5v12.7.0
於 2025/2/15v12.5.0
於 2025/1/22v12.3.0
於 2025/1/259f75
- feat(toValue): 棄用 @vueuse/shared
中的 toValue
,改用 Vue 原生型別v12.1.0
於 2024/12/22v12.0.0-beta.1
於 2024/11/21v11.3.0
於 2024/11/21v10.8.0
於 2024/2/20a086e
- fix: 更嚴格的類型v10.7.0
於 2023/12/5v10.6.0
於 2023/11/9v10.4.0
於 2023/8/25v10.3.0
於 2023/7/30v10.1.1
於 2023/5/1v10.0.0-beta.4
於 2023/4/134d757
- feat(types)!: 將 MaybeComputedRef
重命名為 MaybeRefOrGetter
10e98
- feat(toRef)!: 將 resolveRef
重命名為 toRef
0a72b
- feat(toValue): 將 resolveUnref
重命名為 toValue
v10.0.0-beta.0
於 2023/3/14v9.13.0
於 2023/2/18c2bc6
- fix: 檢查 isFetchOptions
是否為物件