axios 请求方法别名详解:get/post/patch/query 与 getUri、Form 快捷方法的完整用法
axios 的所有 HTTP 请求最终都汇聚到同一个 request 主方法,而 get、post、query 等别名方法只是它在 Axios 类原型上批量生成的语法快捷方式。本文基于官方中文文档「请求别名」章节,结合 lib/core/Axios.js 中的实现源码、index.d.ts 中的 TypeScript 类型声明和 tests/unit/query.test.js 测试用例,完整覆盖每个别名方法的签名、参数语义、getUri 的 URL 预解析机制,以及 postForm/putForm/patchForm 三个表单快捷方法的实现细节,帮助你在实际项目中选对方法、传对参数。
别名方法的设计原则
axios 尽量遵循 RFC 7231 和 RFC 5789 规范,别名方法与这些规范中定义的 HTTP 方法保持一致。从源码结构看,这一设计直接体现在别名方法的生成方式上:lib/core/Axios.js#L267-L306 中用 utils.forEach 分两批为 Axios.prototype 挂载方法——
- 第一批
['delete', 'get', 'head', 'options']是无请求体方法,别名只接收url和config; - 第二批
['post', 'put', 'patch', 'query']是可携带请求体方法,别名接收url、data和config。
两组别名内部都委托给 this.request(mergeConfig(...)),即在调用前把 { method, url, data } 合并进配置对象,因此别名方法与 request 主方法的行为完全等价,区别仅在于参数书写形式。这也意味着:任何配置项(baseURL、headers、timeout、adapter 等)在别名方法上都可以通过第三个参数传入。
axios 与 request:主请求入口
axios 可以通过仅传入配置对象来发起 HTTP 请求,完整的配置对象文档见请求配置。
axios<T, R, D, P>(
url: string | AxiosRequestConfig<D, P>,
config?: AxiosRequestConfig<D, P>
): Promise<R>;
请求方法的泛型参数顺序为 <T, R, D, P>:响应数据、自定义响应、请求数据和查询参数。P 添加在最后,因此现有的显式 T、R 和 D 参数含义保持不变。未提供自定义 R 时,默认 AxiosResponse 会在 response.config 中保留 D 和 P。
这些签名与 index.d.ts#L654-L707 中 Axios 接口的声明一一对应:request、get、delete、head、options、post、put、patch、query 及三个 Form 快捷方法均带 <T, R, D, P> 泛型,返回 Promise<AxiosResponseResult<T, R, D, P>>。
request 主方法
request 方法是发起 HTTP 请求的主方法,接受一个配置对象并返回解析为响应对象的 Promise,可用于发起任意类型的 HTTP 请求,包括别名方法未覆盖的场景(如 method: 'query' 的通用写法,见下文)。
axios.request<T, R, D, P>(config: AxiosRequestConfig<D, P>): Promise<R>;
从源码看,request 的内部流程(lib/core/Axios.js#L82-L151)值得注意:
- 若第一个参数是字符串,则视作 fetch 风格的
axios(url, config)写法,把字符串塞进config.url; - 用
mergeConfig(this.defaults, config)合并实例默认值与本次请求配置; - 最终
config.method取config.method || this.defaults.method || 'get'并转小写,所以配置里写'GET'和'get'效果相同。
无请求体的方法别名
以下四个方法接受 URL 和可选配置对象,返回解析为响应对象的 Promise。
get
axios.get<T, R, D, P>(url: string, config?: AxiosRequestConfig<D, P>): Promise<R>;
delete
delete 是 JavaScript 保留字,但在对象属性和原型方法位置上是合法标识符,因此可以直接写成 axios.delete(url)。
axios.delete<T, R, D, P>(url: string, config?: AxiosRequestConfig<D, P>): Promise<R>;
head
axios.head<T, R, D, P>(url: string, config?: AxiosRequestConfig<D, P>): Promise<R>;
options
axios.options<T, R, D, P>(url: string, config?: AxiosRequestConfig<D, P>): Promise<R>;
这四个别名的实现(lib/core/Axios.js#L268-L279)有一个容易忽略的细节:data 字段取的是 config.data——即如果你在 config 里显式传了 data,它仍会随请求发出(DELETE 请求带请求体正是 RFC 5789 的合法场景),未传则为 undefined。
可携带请求体的方法别名
以下三个方法与 post 同属"带数据"家族,均接受 URL、可选数据对象和可选配置对象。
post
axios.post<T, R, D, P>(url: string, data?: D, config?: AxiosRequestConfig<D, P>): Promise<R>;
put
axios.put<T, R, D, P>(url: string, data?: D, config?: AxiosRequestConfig<D, P>): Promise<R>;
patch
axios.patch<T, R, D, P>(url: string, data?: D, config?: AxiosRequestConfig<D, P>): Promise<R>;
对象形式的 data 会经由 dispatchRequest 中的请求转换管线序列化为 JSON 字符串,并自动附带 Content-Type: application/json(除非你显式指定了其他内容类型)。
query:可携带请求体的安全读取方法
query 方法用于发起 QUERY 请求,这是一种安全(safe)且幂等(idempotent)的、可以携带请求体的方法。它接受 URL、可选数据对象和可选配置对象,返回解析为响应对象的 Promise。当读取类操作的参数过于复杂或敏感、不适合放在 URL 中时,可以使用该方法。
axios.query<T, R, D, P>(url: string, data?: D, config?: AxiosRequestConfig<D, P>): Promise<R>;
// 将复杂的搜索条件作为请求体发送
const { data } = await axios.query("/api/search", {
selector: ["name", "email"],
filter: { active: true, role: "admin" },
});
草案规范警示:QUERY 方法目前由 IETF 的 Internet-Draft(safe-method-w-body)定义,尚未成为正式标准。其语义乃至方法名称都可能在最终发布前发生变化,并且服务器、代理和 CDN 的支持情况参差不齐。在用于生产环境之前,请确认你的整个链路(包括中间代理和 CDN)都能够正确处理 QUERY 请求。
仓库内的 tests/unit/query.test.js 用真实 HTTP 服务器验证了 QUERY 请求的行为,可以作为使用依据:
- 服务端收到的
req.method为大写QUERY,请求体是 JSON 字符串且Content-Type包含application/json(对应源码中query被归入"带数据"方法族、走 JSON 转换管线); - 实例上的
instance.query('/resources', ...)会正确继承baseURL(测试断言请求落到/api/resources); - 通用写法
axios({ method: 'query', url, data })与别名写法行为一致。
值得注意的是,lib/defaults/index.js#L173-L175 中 defaults.headers 为 ['delete', 'get', 'head', 'post', 'put', 'patch', 'query'] 每个方法都预留了独立的请求头桶,因此在配置里写 headers: { query: { ... } } 可以只为 QUERY 请求设置专属请求头,_request 内部会按 config.method 自动合并该桶(lib/core/Axios.js#L153-L164)。
getUri:不发请求地解析最终 URL
getUri 方法返回给定配置在不实际发起请求的情况下会发送的 URL。它会应用 baseURL、paramsSerializer 和 params,因此你拿到的字符串与 axios 实际发出的 URL 相同。可用于构建链接、调试序列化逻辑,或在另一个请求中复用解析后的 URL。
axios.getUri(config?: AxiosRequestConfig): string;
const url = axios.getUri({
url: "/users",
baseURL: "https://api.example.com",
params: { active: true, role: "admin" },
});
// "https://api.example.com/users?active=true&role=admin"
在实例上调用 getUri(instance.getUri(config))会继承该实例的 baseURL、params 和 paramsSerializer 默认值——这正是 lib/core/Axios.js#L260-L264 中 mergeConfig(this.defaults, config) 先合并实例默认值的原因。
getUri 的实现只有三步,非常适合对照理解:
mergeConfig(this.defaults, config):合并实例默认值;buildFullPath(config.baseURL, config.url, ...):拼接baseURL与相对路径(lib/core/buildFullPath.js);buildURL(fullPath, config.params, config.paramsSerializer):把查询参数序列化并追加到 URL(lib/helpers/buildURL.js#L31-L68)。
从 lib/helpers/buildURL.js 的源码可以看到几个实用细节:
- 支持自定义序列化:
paramsSerializer传函数时视作{ serialize: fn },也可以传encode自定义编码;默认编码器会把encodeURIComponent产生的%3A、%24、%2C、%20还原为:、$、,、+; - 若 URL 已带
?,参数以&追加;遇到#片段时会先截掉再拼接; params为URLSearchParams实例时直接toString(),对象则交给AxiosURLSearchParams处理(支持嵌套参数序列化)。
所以调试"参数为什么被编码成这样"时,getUri 是最直接的验证手段:它走的就是真实请求的同一条 URL 构建路径。
表单数据快捷方法:postForm / putForm / patchForm
这些方法与上述对应方法等价,但会预设 Content-Type 为 multipart/form-data,是上传文件或提交 HTML 表单的推荐方式。
从 lib/core/Axios.js#L281-L306 的实现看,postForm、putForm、patchForm 并非独立方法,而是由 generateHTTPMethod(true) 工厂与基础方法共用同一套生成逻辑,唯一差异是请求头中硬编码了 'Content-Type': 'multipart/form-data',该头随后与你的 config.headers 合并。
postForm
axios.postForm<T, R, D, P>(url: string, data?: D, config?: AxiosRequestConfig<D, P>): Promise<R>;
// 从浏览器文件输入框上传文件
await axios.postForm("/api/upload", {
file: document.querySelector("#fileInput").files[0],
description: "Profile photo",
});
putForm
axios.putForm<T, R, D, P>(url: string, data?: D, config?: AxiosRequestConfig<D, P>): Promise<R>;
// 用表单数据替换资源
await axios.putForm("/api/users/1/avatar", {
avatar: document.querySelector("#avatarInput").files[0],
});
patchForm
axios.patchForm<T, R, D, P>(url: string, data?: D, config?: AxiosRequestConfig<D, P>): Promise<R>;
// 使用表单数据更新特定字段
await axios.patchForm("/api/users/1", {
displayName: "New Name",
avatar: document.querySelector("#avatarInput").files[0],
});
postForm、putForm 和 patchForm 接受与基础方法相同的所有数据类型——普通对象、FormData、FileList 以及 HTMLFormElement。更多示例请参阅文件上传。
源码中还有一个刻意的缺失:query 虽然与 post/put/patch 同属"带数据"方法族,但不会生成 queryForm——源码注释说明 QUERY 是安全的幂等读取方法,multipart/form-data 请求体不符合其语义(lib/core/Axios.js#L301-L305)。
实例上的别名方法与调用链
以上所有别名不仅存在于默认导出的 axios 对象上,也存在于 axios.create() 创建的每个实例上。lib/axios.js#L28-L44 中的 createInstance 会执行 utils.extend(instance, Axios.prototype, context, ...),把包括全部别名方法、getUri、request 在内的原型方法逐个拷贝到实例对象上,并以实例自身为上下文绑定——这就是"实例方法继承实例默认值"的机制来源。
一次 axios.post(url, data, config) 的完整调用链为:
axios.post(实例方法,lib/axios.js 从原型拷贝而来)
→ this.request(mergeConfig(config, { method, url, data, headers? }))
→ Axios.prototype.request → _request(lib/core/Axios.js)
→ mergeConfig(this.defaults, config) // 合并实例默认值
→ 构建 request/response 拦截器链
→ dispatchRequest → 适配器(xhr / http / fetch)发出真实请求
由此可以给出几条实操建议:
- 需要按 HTTP 方法设置专属请求头时,用
headers: { get: {...}, post: {...} }这样的方法桶写法,_request会按最终config.method自动选用; - 别名方法未覆盖的需求(如同时想覆盖 method 又走通用配置对象),直接
axios({ method: 'query', url, data, ... })即可,测试用例 tests/unit/query.test.js#L149-L171 验证了两种写法等价; - 构建分享链接、缓存键或调试参数序列化时优先用
getUri,它零网络开销且与实际请求共用同一套 URL 构建逻辑。
小结
| 方法 | 请求体 | 预设 Content-Type | 说明 |
|---|---|---|---|
request(config) |
任意 | 按数据类型 | 主方法,可发起任意 HTTP 请求 |
get / delete / head / options |
可选(显式传 data 才发出) |
无 | RFC 7231 无体方法 |
post / put / patch |
可选 | application/json(对象数据时) |
RFC 7231 方法 |
query |
可选 | application/json(对象数据时) |
IETF 草案的安全幂等读取方法,注意链路兼容性 |
postForm / putForm / patchForm |
可选 | multipart/form-data |
文件上传与 HTML 表单提交快捷方式,无 queryForm |
getUri(config) |
— | — | 不发请求,返回 baseURL + params + paramsSerializer 解析后的最终 URL |
所有别名最终都收敛于 request 主方法(lib/core/Axios.js#L267-L306),掌握这一关系后,无论 TypeScript 声明(index.d.ts)、默认请求头配置(lib/defaults/index.js)还是测试(tests/unit/query.test.js),都可以顺着同一条实现脉络阅读和验证。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00