upfetch 是一个高级的 fetch 客户端构建器,具有标准模式验证、自动响应解析、智能默认值等功能。旨在使数据获取类型安全且开发人员友好,同时保持熟悉的 fetch API。
警告 此中文翻译由人工智能生成。如果您发现任何错误或有改进建议,欢迎提交 Pull Request。
- 🚀 轻量级 - 压缩后仅 1.2kB,无依赖
- 🔒 类型安全 - 使用 zod、valibot 或 arktype 验证 API 响应
- 🛠️ 实用的 API - 使用对象作为
params
和body
,自动获取解析后的响应 - 🎨 灵活配置 - 一次设置
baseUrl
或headers
等默认值,随处使用 - 🤝 熟悉的使用方式 - 与 fetch 相同的 API,但具有额外选项和合理的默认值
npm i up-fetch
创建新的 upfetch 实例:
import { up } from 'up-fetch'
export const upfetch = up(fetch)
使用模式验证进行 fetch 请求:
import { upfetch } from './upfetch'
import { z } from 'zod'
const user = await upfetch('https://a.b.c/users/1', {
schema: z.object({
id: z.number(),
name: z.string(),
avatar: z.string().url(),
}),
})
响应已经基于模式进行了解析和正确的类型推断。
upfetch 扩展了原生 fetch API,这意味着所有标准的 fetch 选项都可用。
创建实例时为所有请求设置默认值:
const upfetch = up(fetch, () => ({
baseUrl: 'https://a.b.c',
timeout: 30000,
}))
查看 API 参考 获取完整的选项列表。
👎 使用原生 fetch:
fetch(
`https://api.example.com/todos?search=${search}&skip=${skip}&take=${take}`,
)
👍 使用 upfetch:
upfetch('/todos', {
params: { search, skip, take },
})
使用 serializeParams 选项自定义查询参数序列化。
👎 使用原生 fetch:
fetch('https://api.example.com/todos', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title: 'New Todo' }),
})
👍 使用 upfetch:
upfetch('/todos', {
method: 'POST',
body: { title: 'New Todo' },
})
upfetch 也支持所有 fetch body 类型。
查看 serializeBody 选项自定义请求体序列化。
由于 upfetch 遵循 Standard Schema Specification,它可以与任何实现该规范的模式库一起使用。
查看完整列表 这里。
👉 使用 zod 3.24+
import { z } from 'zod'
const posts = await upfetch('/posts/1', {
schema: z.object({
id: z.number(),
title: z.string(),
}),
})
👉 使用 valibot 1.0+
import { object, string, number } from 'valibot'
const posts = await upfetch('/posts/1', {
schema: object({
id: number(),
title: string(),
}),
})
使用简单的钩子控制请求/响应生命周期:
const upfetch = up(fetch, () => ({
onRequest: (options) => {
// 在发出请求之前调用,可以在此处修改选项
},
onSuccess: (data, options) => {
// 请求成功完成时调用
},
onError: (error, options) => {
// 请求失败时调用
},
}))
为单个请求设置超时:
upfetch('/todos', {
timeout: 3000,
})
为所有请求设置默认超时:
const upfetch = up(fetch, () => ({
timeout: 5000,
}))
当 response.ok
为 false
时抛出。
使用 isResponseError
识别此错误类型。
import { isResponseError } from 'up-fetch'
try {
await upfetch('/todos/1')
} catch (error) {
if (isResponseError(error)) {
console.log(error.status)
}
}
- 使用 parseRejected 选项抛出自定义错误。
- 使用 reject 选项决定何时抛出错误。
当模式验证失败时抛出。
使用 isValidationError
识别此错误类型。
import { isValidationError } from 'up-fetch'
try {
await upfetch('/todos/1', { schema: todoSchema })
} catch (error) {
if (isValidationError(error)) {
console.log(error.issues)
}
}
通过设置默认 header 轻松为所有请求添加身份验证:
const upfetch = up(fetch, () => ({
headers: { Authorization: localStorage.getItem('bearer-token') },
}))
在每次请求之前从 localStorage
获取 bearer token。
只需传递 undefined
:
upfetch('/todos', {
signal: undefined,
})
从 form
获取 FormData。
const form = document.querySelector('#my-form')
upfetch('/todos', {
method: 'POST',
body: new FormData(form),
})
或从对象创建 FormData:
import { serialize } from 'object-to-formdata'
const upfetch = up(fetch, () => ({
serializeBody: (body) => serialize(body),
}))
upfetch('https://a.b.c', {
method: 'POST',
body: { file: new File(['foo'], 'foo.txt') },
})
由于 upfetch 是 "fetch 无关的",你可以使用 undici 代替原生 fetch 实现。
在单个请求中:
import { fetch, Agent } from 'undici'
const upfetch = up(fetch)
const data = await upfetch('https://a.b.c', {
dispatcher: new Agent({
keepAliveTimeout: 10,
keepAliveMaxTimeout: 10,
}),
})
在所有请求中:
import { fetch, Agent } from 'undici'
const upfetch = up(fetch, () => ({
dispatcher: new Agent({
keepAliveTimeout: 10,
keepAliveMaxTimeout: 10,
}),
}))
你可以创建多个具有不同默认值的 upfetch 实例:
const fetchJson = up(fetch)
const fetchBlob = up(fetch, () => ({
parseResponse: (res) => res.blob(),
}))
const fetchText = up(fetch, () => ({
parseResponse: (res) => res.text(),
}))
虽然 Fetch API 在响应不正常时不会抛出错误,但 upfetch 会抛出 ResponseError
。
如果你更愿意将错误作为值处理,将 reject
设置为返回 false
。
这允许你自定义 parseResponse
函数以结构化格式返回成功数据和错误响应。
const upfetch = up(fetch, () => ({
reject: () => false,
parseResponse: async (response) => {
const json = await response.json()
return response.ok
? { data: json, error: null }
: { data: null, error: json }
},
}))
使用方法:
const { data, error } = await upfetch('/users/1')
默认情况下,upfetch 能够自动解析 json
和 text
成功响应。
当 reject
返回 false
时调用 parseResponse
方法。
你可以使用该选项解析其他响应类型。
const upfetch = up(fetch, () => ({
parseResponse: (response) => response.blob(),
}))
💡 注意,只有当 reject
返回 false
时才会调用 parseResponse
方法。
默认情况下,当 reject
返回 true
时,upfetch 会抛出 ResponseError
。
如果你想抛出自定义错误,可以向 parseRejected
选项传递一个函数。
const upfetch = up(fetch, () => ({
parseRejected: async (response) => {
const status = response.status
const data = await response.json()
return new CustomError(status, data)
},
}))
默认情况下,upfetch 使用 URLSearchParams
序列化参数。
你可以通过向 serializeParams
选项传递函数来自定义参数序列化。
import queryString from 'query-string'
const upfetch = up(fetch, () => ({
serializeParams: (params) => queryString.stringify(params),
}))
默认情况下,upfetch 使用 JSON.stringify
序列化普通对象。
你可以通过向 serializeBody
选项传递函数来自定义请求体序列化。它允许你:
- 限制有效的请求体类型,通过类型化其第一个参数
- 将请求体转换为有效的
BodyInit
类型
以下示例展示如何将有效请求体类型限制为 Record<string, any>
并使用 JSON.stringify
序列化:
// 将请求体类型限制为 Record<string, any> 并序列化
const upfetch = up(fetch, () => ({
serializeBody: (body: Record<string, any>) => JSON.stringify(body),
}))
// ❌ 类型错误:请求体不是 Record<string, any>
upfetch('https://a.b.c/todos', {
method: 'POST',
body: [['title', 'New Todo']],
})
// ✅ 使用 Record<string, any> 正常工作
upfetch('https://a.b.c/todos', {
method: 'POST',
body: { title: 'New Todo' },
})
以下示例使用 superjson
序列化请求体。有效的请求体类型从 SuperJSON.stringify
推断。
import SuperJSON from 'superjson'
const upfetch = up(fetch, () => ({
serializeBody: SuperJSON.stringify,
}))
默认选项接收 fetcher 参数,这允许你根据实际请求定制默认值。
const upfetch = up(fetch, (input, options) => ({
baseUrl: 'https://example.com/',
headers: {
// 仅为受保护路由添加身份验证
Authorization:
typeof input === 'string' && input.startsWith('/api/protected/')
? `Bearer ${getToken()}`
: undefined,
},
// 仅为公共端点添加跟踪参数
params: {
trackingId:
typeof input === 'string' && input.startsWith('/public/')
? crypto.randomUUID()
: undefined,
},
// 为长时间运行的操作增加超时时间
timeout:
typeof input === 'string' && input.startsWith('/export/') ? 30000 : 5000,
}))
创建具有可选默认选项的新 upfetch 实例。
function up(
fetchFn: typeof globalThis.fetch,
getDefaultOptions?: (fetcherOptions: FetcherOptions) => DefaultOptions,
): UpFetch
选项 | 签名 | 描述 |
---|---|---|
baseUrl |
string |
所有请求的基础 URL。 |
params |
object |
默认查询参数。 |
onRequest |
(options) => void |
在发出请求之前执行。 |
onError |
(error, options) => void |
发生错误时执行。 |
onSuccess |
(data, options) => void |
请求成功完成时执行。 |
parseResponse |
(response, options) => data |
默认成功响应解析器。 如果省略,将自动解析 json 和 text 响应。 |
parseRejected |
(response, options) => error |
默认错误响应解析器。 如果省略,将自动解析 json 和 text 响应。 |
serializeBody |
(body) => BodyInit |
默认请求体序列化器。 通过类型化其第一个参数限制有效的 body 类型。 |
serializeParams |
(params) => string |
默认查询参数序列化器。 |
timeout |
number |
默认超时时间(毫秒)。 |
reject |
(response) => boolean |
决定何时拒绝响应。 |
...以及所有其他 fetch 选项 |
使用给定选项发出 fetch 请求。
function upfetch(
url: string | URL | Request,
options?: FetcherOptions,
): Promise<any>
选项:
选项 | 签名 | 描述 |
---|---|---|
baseUrl |
string |
请求的基础 URL。 |
params |
object |
查询参数。 |
parseResponse |
(response, options) => data |
成功响应解析器。 |
parseRejected |
(response, options) => error |
错误响应解析器。 |
schema |
StandardSchemaV1 |
用于验证响应的模式。 模式必须遵循 Standard Schema Specification。 |
serializeBody |
(body) => BodyInit |
请求体序列化器。 通过类型化其第一个参数限制有效的 body 类型。 |
serializeParams |
(params) => string |
查询参数序列化器。 |
timeout |
number |
超时时间(毫秒)。 |
reject |
(response) => boolean |
决定何时拒绝响应。 |
...以及所有其他 fetch 选项 |
检查错误是否为 ResponseError
。
检查错误是否为 ValidationError
。
确定值是否可以安全转换为 json
。
以下被认为是可 JSON 化的:
- 普通对象
- 数组
- 具有
toJSON
方法的类实例
查看功能比较表,了解 upfetch 与其他获取库的比较。
- ✅ 浏览器 (Chrome, Firefox, Safari, Edge)
- ✅ Node.js (20.3.0+)
- ✅ Bun
- ✅ Deno
- ✅ Cloudflare Workers
- ✅ Vercel Edge Runtime