基于 Promise 的 HTTP 客户端,适用于浏览器和 Node.js
网站 •
文档
[](https://www.npmjs.org/package/axios)
[](https://cdnjs.com/libraries/axios)
[](https://github.com/axios/axios/actions/workflows/ci.yml)
[](https://gitpod.io/#https://github.com/axios/axios)
[](https://coveralls.io/r/mzabriskie/axios)
[](https://packagephobia.now.sh/result?p=axios)
[](https://bundlephobia.com/package/axios@latest)
[](https://npm-stat.com/charts.html?package=axios)
[](https://gitter.im/mzabriskie/axios)
[](https://www.codetriage.com/axios/axios)
[](https://snyk.io/test/npm/axios)
[](CONTRIBUTORS.md)
## 目录
- [功能特性](#features)
- [浏览器支持](#browser-support)
- [安装](#installing)
- [包管理器](#package-manager)
- [CDN](#cdn)
- [示例](#example)
- [Axios API](#axios-api)
- [请求方法别名](#request-method-aliases)
- [并发 👎](#concurrency-deprecated)
- [创建实例](#creating-an-instance)
- [实例方法](#instance-methods)
- [请求配置](#request-config)
- [响应结构](#response-schema)
- [配置默认值](#config-defaults)
- [全局 axios 默认值](#global-axios-defaults)
- [自定义实例默认值](#custom-instance-defaults)
- [配置优先级顺序](#config-order-of-precedence)
- [拦截器](#interceptors)
- [多个拦截器](#multiple-interceptors)
- [错误处理](#handling-errors)
- [处理超时](#handling-timeouts)
- [取消请求](#cancellation)
- [AbortController](#abortcontroller)
- [CancelToken 👎](#canceltoken-deprecated)
- [使用 application/x-www-form-urlencoded 格式](#using-applicationx-www-form-urlencoded-format)
- [URLSearchParams](#urlsearchparams)
- [查询字符串](#query-string-older-browsers)
- [🆕 自动序列化](#-automatic-serialization-to-urlsearchparams)
- [使用 multipart/form-data 格式](#using-multipartform-data-format)
- [FormData](#formdata)
- [🆕 自动序列化](#-automatic-serialization-to-formdata)
- [文件上传](#files-posting)
- [HTML 表单上传](#-html-form-posting-browser)
- [🆕 进度捕获](#-progress-capturing)
- [🆕 速率限制](#-rate-limiting)
- [🆕 AxiosHeaders](#-axiosheaders)
- [🔥 Fetch adapter](#-fetch-adapter)
- [🔥 自定义 fetch](#-custom-fetch)
- [🔥 在 Tauri 中使用](#-using-with-tauri)
- [🔥 在 SvelteKit 中使用](#-using-with-sveltekit-)
- [🔥 HTTP2](#-http2)
- [Semver](#semver)
- [Promises](#promises)
- [TypeScript](#typescript)
- [资源](#resources)
- [致谢](#credits)
- [许可证](#license)
## 功能特性
- **浏览器请求:** 在浏览器中直接发起 [XMLHttpRequests](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest)。
- **Node.js 请求:** 在 Node.js 环境中发起 [http](https://nodejs.org/api/http.html) 请求。
- **基于 Promise:** 完全支持 [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) API,让异步代码更简单。
- **拦截器:** 拦截请求和响应,以添加自定义逻辑或转换数据。
- **数据转换:** 自动转换请求和响应数据。
- **取消请求:** 使用内置机制取消请求。
- **自动处理 JSON:** 自动序列化和解析 [JSON](https://www.json.org/json-en.html) 数据。
- **表单序列化:** 🆕 自动将数据对象序列化为 `multipart/form-data` 或 `x-www-form-urlencoded` 格式。
- **XSRF 防护:** 客户端支持防御[跨站请求伪造](https://en.wikipedia.org/wiki/Cross-site_request_forgery)。
## 浏览器支持
| Chrome | Firefox | Safari | Opera | Edge |
| :------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------: |
|  |  |  |  |  |
| Latest ✔ | Latest ✔ | Latest ✔ | Latest ✔ | Latest ✔ |
[](https://saucelabs.com/u/axios)
## 安装
### 包管理器
使用 npm:
```
$ npm install axios
```
使用 bower:
```
$ bower install axios
```
使用 yarn:
```
$ yarn add axios
```
使用 pnpm:
```
$ pnpm add axios
```
使用 bun:
```
$ bun add axios
```
安装完包后,你可以使用 `import` 或 `require` 方式导入该库:
```
import axios, { isCancel, AxiosError } from "axios";
```
由于命名导出只是对 Axios 工厂函数的重新导出,因此你也可以使用默认导出:
```
import axios from "axios";
console.log(axios.isCancel("something"));
```
如果你使用 `require` 导入,**只有默认导出可用**:
```
const axios = require("axios");
console.log(axios.isCancel("something"));
```
对于某些打包器和某些 ES6 代码检查工具,你可能需要执行以下操作:
```
import { default as axios } from "axios";
```
如果在尝试将模块导入自定义或旧版环境时出现问题,
你可以尝试直接导入模块包:
```
const axios = require("axios/dist/browser/axios.cjs"); // browser commonJS bundle (ES2017)
// const axios = require('axios/dist/node/axios.cjs'); // node commonJS bundle (ES2017)
```
### CDN
使用 jsDelivr CDN (ES5 UMD 浏览器模块):
```
```
使用 unpkg CDN:
```
```
## 示例
```
import axios from "axios";
//const axios = require('axios'); // legacy way
try {
const response = await axios.get("/user?ID=12345");
console.log(response);
} catch (error) {
console.error(error);
}
// Optionally the request above could also be done as
axios
.get("/user", {
params: {
ID: 12345,
},
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
})
.finally(function () {
// always executed
});
// Want to use async/await? Add the `async` keyword to your outer function/method.
async function getUser() {
try {
const response = await axios.get("/user?ID=12345");
console.log(response);
} catch (error) {
console.error(error);
}
}
```
执行 `POST` 请求
```
const response = await axios.post("/user", {
firstName: "Fred",
lastName: "Flintstone",
});
console.log(response);
```
执行多个并发请求
```
function getUserAccount() {
return axios.get("/user/12345");
}
function getUserPermissions() {
return axios.get("/user/12345/permissions");
}
Promise.all([getUserAccount(), getUserPermissions()]).then(function (results) {
const acct = results[0];
const perm = results[1];
});
```
## axios API
可以通过向 `axios` 传递相关配置来发起请求。
##### axios(config)
```
// Send a POST request
axios({
method: "post",
url: "/user/12345",
data: {
firstName: "Fred",
lastName: "Flintstone",
},
});
```
```
// GET request for remote image in node.js
const response = await axios({
method: "get",
url: "https://bit.ly/2mTM3nY",
responseType: "stream",
});
response.data.pipe(fs.createWriteStream("ada_lovelace.jpg"));
```
##### axios(url[, config])
```
// Send a GET request (default method)
axios("/user/12345");
```
### 请求方法别名
为了方便起见,为所有常用的请求方法提供了别名。
##### axios.request(config)
##### axios.get(url[, config])
##### axios.delete(url[, config])
##### axios.head(url[, config])
##### axios.options(url[, config])
##### axios.post(url[, data[, config]])
##### axios.put(url[, data[, config]])
##### axios.patch(url[, data[, config]])
###### 注意
使用别名方法时,不需要在 config 中指定 `url`、`method` 和 `data` 属性。
### 并发 (已弃用)
请使用 `Promise.all` 替换以下函数。
用于处理并发请求的辅助函数。
axios.all(iterable)
axios.spread(callback)
### 创建实例
你可以使用自定义配置创建一个 axios 的新实例。
##### axios.create([config])
```
const instance = axios.create({
baseURL: "https://some-domain.com/api/",
timeout: 1000,
headers: { "X-Custom-Header": "foobar" },
});
```
### 实例方法
可用的实例方法如下所示。指定的配置将与实例的配置合并。
##### axios#request(config)
##### axios#get(url[, config])
##### axios#delete(url[, config])
##### axios#head(url[, config])
##### axios#options(url[, config])
##### axios#post(url[, data[, config]])
##### axios#put(url[, data[, config]])
##### axios#patch(url[, data[, config])
##### axios#getUri([config])
## 请求配置
这些是用于发起请求的可用配置选项。只有 `url` 是必需的。如果未指定 `method`,请求将默认使用 `GET` 方法。
```
{
// `url` is the server URL that will be used for the request
url: '/user',
// `method` is the request method to be used when making the request
method: 'get', // default
// `baseURL` will be prepended to `url` unless `url` is absolute and the option `allowAbsoluteUrls` is set to true.
// It can be convenient to set `baseURL` for an instance of axios to pass relative URLs
// to the methods of that instance.
baseURL: 'https://some-domain.com/api/',
// `allowAbsoluteUrls` determines whether or not absolute URLs will override a configured `baseUrl`.
// When set to true (default), absolute values for `url` will override `baseUrl`.
// When set to false, absolute values for `url` will always be prepended by `baseUrl`.
allowAbsoluteUrls: true,
// `transformRequest` allows changes to the request data before it is sent to the server
// This is only applicable for request methods 'PUT', 'POST', 'PATCH' and 'DELETE'
// The last function in the array must return a string or an instance of Buffer, ArrayBuffer,
// FormData or Stream
// You may modify the headers object.
transformRequest: [function (data, headers) {
// Do whatever you want to transform the data
return data;
}],
// `transformResponse` allows changes to the response data to be made before
// it is passed to then/catch
transformResponse: [function (data) {
// Do whatever you want to transform the data
return data;
}],
// `headers` are custom headers to be sent
headers: {'X-Requested-With': 'XMLHttpRequest'},
// `params` are the URL parameters to be sent with the request
// Must be a plain object or a URLSearchParams object
params: {
ID: 12345
},
// `paramsSerializer` is an optional config that allows you to customize serializing `params`.
paramsSerializer: {
// Custom encoder function which sends key/value pairs in an iterative fashion.
encode?: (param: string): string => { /* Do custom operations here and return transformed string */ },
// Custom serializer function for the entire parameter. Allows the user to mimic pre 1.x behaviour.
serialize?: (params: Record
, options?: ParamsSerializerOptions ),
// Configuration for formatting array indexes in the params.
indexes: false // Three available options: (1) indexes: null (leads to no brackets), (2) (default) indexes: false (leads to empty brackets), (3) indexes: true (leads to brackets with indexes).
},
// `data` is the data to be sent as the request body
// Only applicable for request methods 'PUT', 'POST', 'DELETE', and 'PATCH'
// When no `transformRequest` is set, it must be of one of the following types:
// - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
// - Browser only: FormData, File, Blob
// - Node only: Stream, Buffer, FormData (form-data package)
data: {
firstName: 'Fred'
},
// syntax alternative to send data into the body
// method post
// only the value is sent, not the key
data: 'Country=Brasil&City=Belo Horizonte',
// `timeout` specifies the number of milliseconds before the request times out.
// If the request takes longer than `timeout`, the request will be aborted.
timeout: 1000, // default is `0` (no timeout)
// `withCredentials` indicates whether or not cross-site Access-Control requests
// should be made using credentials
withCredentials: false, // default
// `adapter` allows custom handling of requests which makes testing easier.
// Return a promise and supply a valid response (see lib/adapters/README.md)
adapter: function (config) {
/* ... */
},
// Also, you can set the name of the built-in adapter, or provide an array with their names
// to choose the first available in the environment
adapter: 'xhr', // 'fetch' | 'http' | ['xhr', 'http', 'fetch']
// `auth` indicates that HTTP Basic auth should be used, and supplies credentials.
// This will set an `Authorization` header, overwriting any existing
// `Authorization` custom headers you have set using `headers`.
// Please note that only HTTP Basic auth is configurable through this parameter.
// For Bearer tokens and such, use `Authorization` custom headers instead.
auth: {
username: 'janedoe',
password: 's00pers3cret'
},
// `responseType` indicates the type of data that the server will respond with
// options are: 'arraybuffer', 'document', 'json', 'text', 'stream'
// browser only: 'blob'
responseType: 'json', // default
// `responseEncoding` indicates encoding to use for decoding responses (Node.js only)
// Note: Ignored for `responseType` of 'stream' or client-side requests
// options are: 'ascii', 'ASCII', 'ansi', 'ANSI', 'binary', 'BINARY', 'base64', 'BASE64', 'base64url',
// 'BASE64URL', 'hex', 'HEX', 'latin1', 'LATIN1', 'ucs-2', 'UCS-2', 'ucs2', 'UCS2', 'utf-8', 'UTF-8',
// 'utf8', 'UTF8', 'utf16le', 'UTF16LE'
responseEncoding: 'utf8', // default
// `xsrfCookieName` is the name of the cookie to use as a value for the xsrf token
xsrfCookieName: 'XSRF-TOKEN', // default
// `xsrfHeaderName` is the name of the http header that carries the xsrf token value
xsrfHeaderName: 'X-XSRF-TOKEN', // default
// `undefined` (default) - set XSRF header only for the same origin requests
withXSRFToken: boolean | undefined | ((config: InternalAxiosRequestConfig) => boolean | undefined),
// `withXSRFToken` controls whether Axios reads the XSRF cookie and sets the XSRF header.
// - `undefined` (default): the XSRF header is set only for same-origin requests.
// - `true`: attempt to set the XSRF header for all requests (including cross-origin).
// - `false`: never set the XSRF header.
// - function: a callback that receives the request `config` and returns `true`,
// `false`, or `undefined` to decide per-request behavior.
//
// Note about `withCredentials`: `withCredentials` controls whether cross-site
// requests include credentials (cookies and HTTP auth). In older Axios versions,
// setting `withCredentials: true` implicitly caused Axios to set the XSRF header
// for cross-origin requests. Newer Axios separates these concerns: to allow the
// XSRF header to be sent for cross-origin requests you should set both
// `withCredentials: true` and `withXSRFToken: true`.
//
// Example:
// axios.get('/user', { withCredentials: true, withXSRFToken: true });
// `onUploadProgress` allows handling of progress events for uploads
// browser & node.js
onUploadProgress: function ({loaded, total, progress, bytes, estimated, rate, upload = true}) {
// Do whatever you want with the Axios progress event
},
// `onDownloadProgress` allows handling of progress events for downloads
// browser & node.js
onDownloadProgress: function ({loaded, total, progress, bytes, estimated, rate, download = true}) {
// Do whatever you want with the Axios progress event
},
// `maxContentLength` defines the max size of the http response content in bytes allowed in node.js
maxContentLength: 2000,
// `maxBodyLength` (Node only option) defines the max size of the http request content in bytes allowed
maxBodyLength: 2000,
// `validateStatus` defines whether to resolve or reject the promise for a given
// HTTP response status code. If `validateStatus` returns `true` (or is set to `null`
// or `undefined`), the promise will be resolved; otherwise, the promise will be
// rejected.
validateStatus: function (status) {
return status >= 200 && status < 300; // default
},
// `maxRedirects` defines the maximum number of redirects to follow in node.js.
// If set to 0, no redirects will be followed.
maxRedirects: 21, // default
// `beforeRedirect` defines a function that will be called before redirect.
// Use this to adjust the request options upon redirecting,
// to inspect the latest response headers,
// or to cancel the request by throwing an error
// If maxRedirects is set to 0, `beforeRedirect` is not used.
beforeRedirect: (options, { headers }) => {
if (options.hostname === "example.com") {
options.auth = "user:password";
}
},
// `socketPath` defines a UNIX Socket to be used in node.js.
// e.g. '/var/run/docker.sock' to send requests to the docker daemon.
// Only either `socketPath` or `proxy` can be specified.
// If both are specified, `socketPath` is used.
socketPath: null, // default
// `transport` determines the transport method that will be used to make the request.
// If defined, it will be used. Otherwise, if `maxRedirects` is 0,
// the default `http` or `https` library will be used, depending on the protocol specified in `protocol`.
// Otherwise, the `httpFollow` or `httpsFollow` library will be used, again depending on the protocol,
// which can handle redirects.
transport: undefined, // default
// `httpAgent` and `httpsAgent` define a custom agent to be used when performing http
// and https requests, respectively, in node.js. This allows options to be added like
// `keepAlive` that are not enabled by default before Node.js v19.0.0. After Node.js
// v19.0.0, you no longer need to customize the agent to enable `keepAlive` because
// `http.globalAgent` has `keepAlive` enabled by default.
httpAgent: new http.Agent({ keepAlive: true }),
httpsAgent: new https.Agent({ keepAlive: true }),
// `proxy` defines the hostname, port, and protocol of the proxy server.
// You can also define your proxy using the conventional `http_proxy` and
// `https_proxy` environment variables. If you are using environment variables
// for your proxy configuration, you can also define a `no_proxy` environment
// variable as a comma-separated list of domains that should not be proxied.
// Use `false` to disable proxies, ignoring environment variables.
// `auth` indicates that HTTP Basic auth should be used to connect to the proxy, and
// supplies credentials.
// This will set a `Proxy-Authorization` header, overwriting any existing
// `Proxy-Authorization` custom headers you have set using `headers`.
// If the proxy server uses HTTPS, then you must set the protocol to `https`.
proxy: {
protocol: 'https',
host: '127.0.0.1',
// hostname: '127.0.0.1' // Takes precedence over 'host' if both are defined
port: 9000,
auth: {
username: 'mikeymike',
password: 'rapunz3l'
}
},
// `cancelToken` specifies a cancel token that can be used to cancel the request
// (see Cancellation section below for details)
cancelToken: new CancelToken(function (cancel) {
}),
// an alternative way to cancel Axios requests using AbortController
signal: new AbortController().signal,
// `decompress` indicates whether or not the response body should be decompressed
// automatically. If set to `true` will also remove the 'content-encoding' header
// from the responses objects of all decompressed responses
// - Node only (XHR cannot turn off decompression)
decompress: true, // default
// `insecureHTTPParser` boolean.
// Indicates where to use an insecure HTTP parser that accepts invalid HTTP headers.
// This may allow interoperability with non-conformant HTTP implementations.
// Using the insecure parser should be avoided.
// see options https://nodejs.org/dist/latest-v12.x/docs/api/http.html#http_http_request_url_options_callback
// see also https://nodejs.org/en/blog/vulnerability/february-2020-security-releases/#strict-http-header-parsing-none
insecureHTTPParser: undefined, // default
// transitional options for backward compatibility that may be removed in the newer versions
transitional: {
// silent JSON parsing mode
// `true` - ignore JSON parsing errors and set response.data to null if parsing failed (old behaviour)
// `false` - throw SyntaxError if JSON parsing failed
// Important: this option only takes effect when `responseType` is explicitly set to 'json'.
// When `responseType` is omitted (defaults to no value), axios uses `forcedJSONParsing`
// to attempt JSON parsing, but will silently return the raw string on failure regardless
// of this setting. To have invalid JSON throw errors, use:
// { responseType: 'json', transitional: { silentJSONParsing: false } }
silentJSONParsing: true, // default value for the current Axios version
// try to parse the response string as JSON even if `responseType` is not 'json'
forcedJSONParsing: true,
// throw ETIMEDOUT error instead of generic ECONNABORTED on request timeouts
clarifyTimeoutError: false,
// use the legacy interceptor request/response ordering
legacyInterceptorReqResOrdering: true, // default
},
env: {
// The FormData class to be used to automatically serialize the payload into a FormData object
FormData: window?.FormData || global?.FormData
},
formSerializer: {
visitor: (value, key, path, helpers) => {}; // custom visitor function to serialize form values
dots: boolean; // use dots instead of brackets format
metaTokens: boolean; // keep special endings like {} in parameter key
indexes: boolean; // array indexes format null - no brackets, false - empty brackets, true - brackets with indexes
},
// http adapter only (node.js)
maxRate: [
100 * 1024, // 100KB/s upload limit,
100 * 1024 // 100KB/s download limit
]
}
```
## 响应结构
请求的响应包含以下信息。
```
{
// `data` is the response that was provided by the server
data: {},
// `status` is the HTTP status code from the server response
status: 200,
// `statusText` is the HTTP status message from the server response
statusText: 'OK',
// `headers` the HTTP headers that the server responded with
// All header names are lowercase and can be accessed using the bracket notation.
// Example: `response.headers['content-type']`
headers: {},
// `config` is the config that was provided to `axios` for the request
config: {},
// `request` is the request that generated this response
// It is the last ClientRequest instance in node.js (in redirects)
// and an XMLHttpRequest instance in the browser
request: {}
}
```
当使用 `then` 时,你将收到如下的响应:
```
const response = await axios.get("/user/12345");
console.log(response.data);
console.log(response.status);
console.log(response.statusText);
console.log(response.headers);
console.log(response.config);
```
当使用 `catch`,或将[拒绝回调](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then)作为 `then` 的第二个参数传递时,可以通过 `error` 对象获取响应,正如[错误处理](#handling-errors)部分所解释的那样。
## 配置默认值
你可以指定将应用于每个请求的配置默认值。
### 全局 axios 默认值
```
axios.defaults.baseURL = "https://api.example.com";
// Important: If axios is used with multiple domains, the AUTH_TOKEN will be sent to all of them.
// See below for an example using Custom instance defaults instead.
axios.defaults.headers.common["Authorization"] = AUTH_TOKEN;
axios.defaults.headers.post["Content-Type"] =
"application/x-www-form-urlencoded";
```
### 自定义实例默认值
```
// Set config defaults when creating the instance
const instance = axios.create({
baseURL: "https://api.example.com",
});
// Alter defaults after instance has been created
instance.defaults.headers.common["Authorization"] = AUTH_TOKEN;
```
### 配置优先级顺序
配置将按优先级顺序合并。顺序是 [lib/defaults/index.js](https://github.com/axios/axios/blob/main/lib/defaults/index.js#L49) 中的库默认值,然后是实例的 `defaults` 属性,最后是请求的 `config` 参数。后者将优先于前者。这里是一个例子。
```
// Create an instance using the config defaults provided by the library
// At this point the timeout config value is `0` as is the default for the library
const instance = axios.create();
// Override timeout default for the library
// Now all requests using this instance will wait 2.5 seconds before timing out
instance.defaults.timeout = 2500;
// Override timeout for this request as it's known to take a long time
instance.get("/longRequest", {
timeout: 5000,
});
```
## 拦截器
你可以在 `.get()` 或 `.post()` 等方法 resolve 它们的 Promise 之前(在 `then` 或 `catch` 内部的代码之前,或在 `await` 之后)拦截请求或响应
```
const instance = axios.create();
// Add a request interceptor
instance.interceptors.request.use(
function (config) {
// Do something before the request is sent
return config;
},
function (error) {
// Do something with the request error
return Promise.reject(error);
},
);
// Add a response interceptor
instance.interceptors.response.use(
function (response) {
// Any status code that lies within the range of 2xx causes this function to trigger
// Do something with response data
return response;
},
function (error) {
// Any status codes that fall outside the range of 2xx cause this function to trigger
// Do something with response error
return Promise.reject(error);
},
);
```
如果你需要稍后移除拦截器,你可以这样做。
```
const instance = axios.create();
const myInterceptor = instance.interceptors.request.use(function () {
/*...*/
});
axios.interceptors.request.eject(myInterceptor);
```
你还可以清除所有请求或响应拦截器。
```
const instance = axios.create();
instance.interceptors.request.use(function () {
/*...*/
});
instance.interceptors.request.clear(); // Removes interceptors from requests
instance.interceptors.response.use(function () {
/*...*/
});
instance.interceptors.response.clear(); // Removes interceptors from responses
```
你可以为 axios 的自定义实例添加拦截器。
```
const instance = axios.create();
instance.interceptors.request.use(function () {
/*...*/
});
```
当你添加请求拦截器时,默认情况下它们被认为是异步的。这可能会导致 axios 请求的执行延迟
当主线程被阻塞时(底层创建了一个 Promise,而你的请求被放到了调用栈的底部)。如果你的请求拦截器是同步的,你可以在 options 对象中添加一个标志,
该标志会告诉 axios 同步运行代码,从而避免请求执行中的任何延迟。
```
axios.interceptors.request.use(
function (config) {
config.headers.test = "I am only a header!";
return config;
},
null,
{ synchronous: true },
);
```
如果你想根据运行时检查来执行特定的拦截器,
你可以在 options 对象中添加一个 `runWhen` 函数。当且仅当 `runWhen` 的返回值为 `false` 时,请求拦截器才不会被执行。
该函数将被调用并传入 config 对象(不要忘记你也可以将自己的参数绑定到它上面)。当你有一个
只需要在某些时候运行的异步请求拦截器时,这会非常方便。
```
function onGetCall(config) {
return config.method === "get";
}
axios.interceptors.request.use(
function (config) {
config.headers.test = "special get headers";
return config;
},
null,
{ runWhen: onGetCall },
);
```
### 拦截器执行顺序
**重要提示:** 拦截器的执行顺序因其类型而异!
请求拦截器按**相反顺序**执行(LIFO - 后进先出)。这意味着_最后_添加的拦截器会**首先**执行。
响应拦截器按**添加顺序**执行(FIFO - 先进先出)。这意味着_首先_添加的拦截器会**首先**执行。
示例:
```
const instance = axios.create();
const interceptor = (id) => (base) => {
console.log(id);
return base;
};
instance.interceptors.request.use(interceptor("Request Interceptor 1"));
instance.interceptors.request.use(interceptor("Request Interceptor 2"));
instance.interceptors.request.use(interceptor("Request Interceptor 3"));
instance.interceptors.response.use(interceptor("Response Interceptor 1"));
instance.interceptors.response.use(interceptor("Response Interceptor 2"));
instance.interceptors.response.use(interceptor("Response Interceptor 3"));
// Console output:
// Request Interceptor 3
// Request Interceptor 2
// Request Interceptor 1
// [HTTP request is made]
// Response Interceptor 1
// Response Interceptor 2
// Response Interceptor 3
```
### 多个拦截器
假设你添加了多个响应拦截器,
并且当响应成功 (fulfilled) 时:
- 那么每个拦截器都会被执行
- 然后它们将按照添加的顺序执行
- 然后只有最后一个拦截器的结果会被返回
- 然后每个拦截器都会接收到其前一个拦截器的结果
- 并且当成功 处理拦截器抛出异常时
- 那么后面的成功处理拦截器将不会被调用
- 然后将调用后面的拒绝 处理拦截器
- 一旦被捕获,将再次调用后面的另一个成功处理拦截器(就像在 Promise 链中一样)。
阅读[拦截器测试](./test/specs/interceptors.spec.js)以在代码中查看所有这些细节。
## 错误类型
axios 中可能会出现许多不同的错误消息,这些消息可以提供有关错误的具体细节以及调试方向的基础信息。
axios 错误的一般结构如下所示:
| 属性 | 定义 |
| -------- | ---------- |
| message | 错误信息的简短摘要及其失败的状态。 |
| name | 定义了错误的来源。对于 axios,它将始终是 'AxiosError'。 |
| stack | 提供错误的堆栈跟踪信息。 |
| config | 一个 axios 配置对象,其中包含用户在发起请求时定义的特定实例配置 |
| code | 表示一个 axios 识别到的错误。下表列出了内部 axios 错误的具体定义。 |
| status | HTTP 响应状态码。常见的 HTTP 响状态码含义请参见[此处](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes)。
以下是潜在的 axios 识别到的错误列表:
| 代码 | 定义 |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ERR_BAD_OPTION_VALUE | 在 axios 配置中提供了无效的值。 |
| ERR_BAD_OPTION | 在 axios 配置中提供了无效的选项。 |
| ERR_NOT_SUPPORT | 当前 axios 环境不支持该功能或方法。 |
| ERR_DEPRECATED | 在 axios 中使用了已弃用的功能或方法。 |
| ERR_INVALID_URL | 为 axios 请求提供了无效的 URL。 |
| ECONNABORTED | 通常表示请求超时(除非设置了 `transitional.clarifyTimeoutError`)或被浏览器及其插件中止。 |
| ERR_CANCELED | 功能或方法被用户使用 AbortSignal(或 CancelToken)明确取消。 |
| ETIMEDOUT | 请求因超过默认的 axios 时间限制而超时。必须将 `transitional.clarifyTimeoutError` 设置为 `true`,否则将抛出通用的 `ECONNABORTED` 错误。 |
| ERR_NETWORK | 与网络相关的问题。在浏览器中,此错误也可能由 [CORS](https://developer.mozilla.org/ru/docs/Web/HTTP/Guides/CORS) 或[混合内容](https://developer.mozilla.org/en-US/docs/Web/Security/Mixed_content) 策略违规引起。出于安全原因,浏览器不允许 JS 代码澄清错误的真实原因,因此请检查控制台。 |
| ERR_FR_TOO_MANY_REDIRECTS | 请求被重定向的次数过多;超出了 axios 配置中指定的最大重定向次数。 |
| ERR_BAD_RESPONSE | 响应无法正确解析或格式不符合预期。通常与具有 `5xx` 状态码的响应相关。 |
| ERR_BAD_REQUEST | 请求的格式不符合预期或缺少必需的参数。通常与具有 `4xx` 状态码的响应相关。 |
## 错误处理
默认行为是拒绝每一个返回状态码不在 2xx 范围内的响应,并将其视为错误。
```
axios.get("/user/12345").catch(function (error) {
if (error.response) {
// The request was made and the server responded with a status code
// that falls out of the range of 2xx
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
} else if (error.request) {
// The request was made but no response was received
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
// http.ClientRequest in node.js
console.log(error.request);
} else {
// Something happened in setting up the request that triggered an Error
console.log("Error", error.message);
}
console.log(error.config);
});
```
使用 `validateStatus` 配置选项,你可以覆盖默认条件(状态 >= 200 && 状态 < 300)并定义应该抛出错误的 HTTP 状态码。
```
axios.get("/user/12345", {
validateStatus: function (status) {
return status < 500; // Resolve only if the status code is less than 500
},
});
```
使用 `toJSON` 你可以获取一个包含有关 HTTP 错误的更多信息的对象。
```
axios.get("/user/12345").catch(function (error) {
console.log(error.toJSON());
});
```
## 处理超时
```
async function fetchWithTimeout() {
try {
const response = await axios.get("https://example.com/data", {
timeout: 5000, // 5 seconds
});
console.log("Response:", response.data);
} catch (error) {
if (axios.isAxiosError(error) && error.code === "ECONNABORTED") {
console.error("❌ Request timed out!");
} else {
console.error("❌ Error:", error.message);
}
}
}
```
## 取消请求
### AbortController
从 `v0.22.0` 开始,Axios 支持 AbortController 以 fetch API 的方式取消请求:
```
const controller = new AbortController();
axios
.get("/foo/bar", {
signal: controller.signal,
})
.then(function (response) {
//...
});
// cancel the request
controller.abort();
```
### CancelToken `👎已弃用`
你也可以使用 _CancelToken_ 取消请求。
你可以使用 `CancelToken.source` 工厂函数创建一个 cancel token,如下所示:
```
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
axios
.get("/user/12345", {
cancelToken: source.token,
})
.catch(function (thrown) {
if (axios.isCancel(thrown)) {
console.log("Request canceled", thrown.message);
} else {
// handle error
}
});
axios.post(
"/user/12345",
{
name: "new name",
},
{
cancelToken: source.token,
},
);
// cancel the request (the message parameter is optional)
source.cancel("Operation canceled by the user.");
```
你也可以通过向 `CancelToken` 构造函数传递一个 executor 函数来创建一个 cancel token:
```
const CancelToken = axios.CancelToken;
let cancel;
axios.get("/user/12345", {
cancelToken: new CancelToken(function executor(c) {
// An executor function receives a cancel function as a parameter
cancel = c;
}),
});
// cancel the request
cancel();
```
## 使用 `application/x-www-form-urlencoded` 格式
### URLSearchParams
默认情况下,axios 将 JavaScript 对象序列化为 `JSON`。要以 [`application/x-www-form-urlencoded`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST) 格式发送数据,你可以使用 [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) API,该 API 在绝大多数浏览器中都被[支持](http://www.caniuse.com/#feat=urlsearchparams),并且 [Node](https://nodejs.org/api/url.html#url_class_urlsearchparams) 从 v10 版本(2018 年发布)开始支持。
```
const params = new URLSearchParams({ foo: "bar" });
params.append("extraparam", "value");
axios.post("/foo", params);
```
### 查询字符串 (旧版浏览器)
为了兼容非常旧的浏览器,有一个可用的 [polyfill](https://github.com/WebReflection/url-search-params)(请确保对全局环境进行 polyfill)。
或者,你可以使用 [`qs`](https://github.com/ljharb/qs) 库对数据进行编码:
```
const qs = require("qs");
axios.post("/foo", qs.stringify({ bar: 123 }));
```
或者用另一种方式 (ES6),
```
import qs from "qs";
const data = { bar: 123 };
const options = {
method: "POST",
headers: { "content-type": "application/x-www-form-urlencoded" },
data: qs.stringify(data),
url,
};
axios(options);
```
### 旧版 Node.js
对于较旧的 Node.js 引擎,你可以按以下方式使用 [`querystring`](https://nodejs.org/api/querystring.html) 模块:
```
const querystring = require("querystring");
axios.post("https://something.com/", querystring.stringify({ foo: "bar" }));
```
你也可以使用 [`qs`](https://github.com/ljharb/qs) 库。
### 🆕 自动序列化为 URLSearchParams
如果 content-type 请求头被设置为 "application/x-www-form-urlencoded",Axios 将自动将数据对象序列化为 urlencoded 格式。
```
const data = {
x: 1,
arr: [1, 2, 3],
arr2: [1, [2], 3],
users: [
{ name: "Peter", surname: "Griffin" },
{ name: "Thomas", surname: "Anderson" },
],
};
await axios.postForm("https://postman-echo.com/post", data, {
headers: { "content-type": "application/x-www-form-urlencoded" },
});
```
服务器将其处理为:
```
{
x: '1',
'arr[]': [ '1', '2', '3' ],
'arr2[0]': '1',
'arr2[1][0]': '2',
'arr2[2]': '3',
'arr3[]': [ '1', '2', '3' ],
'users[0][name]': 'Peter',
'users[0][surname]': 'griffin',
'users[1][name]': 'Thomas',
'users[1][surname]': 'Anderson'
}
```
如果你的后端 body-parser(如 `express.js` 的 `body-parser`)支持嵌套对象解码,你将在服务端自动获得相同的对象
```
const app = express();
app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies
app.post("/", function (req, res, next) {
// echo body as JSON
res.send(JSON.stringify(req.body));
});
server = app.listen(3000);
```
## 使用 `multipart/form-data` 格式
### FormData
要以 `multipart/form-data` 形式发送数据,你需要将一个 formData 实例作为 payload 传递。
不需要设置 `Content-Type` 请求头,因为 Axios 会根据 payload 的类型进行猜测。
```
const formData = new FormData();
formData.append("foo", "bar");
axios.post("https://httpbin.org/post", formData);
```
在 node.js 中,你可以按以下方式使用 [`form-data`](https://github.com/form-data/form-data) 库:
```
const FormData = require("form-data");
const form = new FormData();
form.append("my_field", "my value");
form.append("my_buffer", Buffer.alloc(10));
form.append("my_file", fs.createReadStream("/foo/bar.jpg"));
axios.post("https://example.com", form);
```
### 🆕 自动序列化为 FormData
从 `v0.27.0` 开始,如果请求的 `Content-Type` 请求头被设置为 `multipart/form-data`,Axios 支持将对象自动序列化为 FormData 对象。
以下请求将以 FormData 格式提交数据(浏览器和 Node.js):
```
import axios from "axios";
axios
.post(
"https://httpbin.org/post",
{ x: 1 },
{
headers: {
"Content-Type": "multipart/form-data",
},
},
)
.then(({ data }) => console.log(data));
```
在 `node.js` 构建版本中,默认使用 ([`form-data`](https://github.com/form-data/form-data)) polyfill。
你可以通过设置 `env.FormData` 配置变量来重载 FormData 类,
但在大多数情况下你可能不需要它:
```
const axios = require("axios");
var FormData = require("form-data");
axios
.post(
"https://httpbin.org/post",
{ x: 1, buf: Buffer.alloc(10) },
{
headers: {
"Content-Type": "multipart/form-data",
},
},
)
.then(({ data }) => console.log(data));
```
Axios FormData 序列化器支持一些特殊结尾标志来执行以下操作:
- `{}` - 使用 JSON.stringify 序列化值
- `[]` - 将类数组对象解包为具有相同键的独立字段
FormData 序列化器通过 `config.formSerializer: object` 属性支持额外的选项来处理罕见情况:
- `visitor: Function` - 用户定义的访问者函数,将通过遵循自定义规则将数据对象递归序列化为 `FormData` 对象。
- `dots: boolean = false` - 使用点表示法而不是括号来序列化数组和对象;
- `metaTokens: boolean = true` - 在 FormData 键中添加特殊结尾标志(例如 `user{}: '{"name": "John"}'`)。
后端的 body-parser 可能会利用此元信息自动将值解析为 JSON。
- `indexes: null|false|true = false` - 控制如何将索引添加到 `flat` 类数组对象的解包键中。
- `null` - 不添加括号 (`arr: 1`, `arr: 2`, `arr: 3`)
- `false`(默认)- 添加空括号 (`arr[]: 1`, `arr[]: 2`, `arr[]: 3`)
- `true` - 添加带索引的括号 (`arr[0]: 1`, `arr[1]: 2`, `arr[2]: 3`)
假设我们有这样一个对象:
```
const obj = {
x: 1,
arr: [1, 2, 3],
arr2: [1, [2], 3],
users: [
{ name: "Peter", surname: "Griffin" },
{ name: "Thomas", surname: "Anderson" },
],
"obj2{}": [{ x: 1 }],
};
```
Axios 序列化器内部将执行以下步骤:
```
const formData = new FormData();
formData.append("x", "1");
formData.append("arr[]", "1");
formData.append("arr[]", "2");
formData.append("arr[]", "3");
formData.append("arr2[0]", "1");
formData.append("arr2[1][0]", "2");
formData.append("arr2[2]", "3");
formData.append("users[0][name]", "Peter");
formData.append("users[0][surname]", "Griffin");
formData.append("users[1][name]", "Thomas");
formData.append("users[1][surname]", "Anderson");
formData.append("obj2{}", '[{"x":1}]');
```
Axios 支持以下快捷方法:`postForm`、`putForm`、`patchForm`
它们只是预先将 `Content-Type` 请求头设置为 `multipart/form-data` 的相应 HTTP 方法。
## 文件上传
你可以轻松提交单个文件:
```
await axios.postForm("https://httpbin.org/post", {
myVar: "foo",
file: document.querySelector("#fileInput").files[0],
});
```
或者作为 `multipart/form-data` 提交多个文件:
```
await axios.postForm("https://httpbin.org/post", {
"files[]": document.querySelector("#fileInput").files,
});
```
可以直接传递 `FileList` 对象:
```
await axios.postForm(
"https://httpbin.org/post",
document.querySelector("#fileInput").files,
);
```
所有文件都将使用相同的字段名发送:`files[]`。
## 🆕 HTML 表单上传 (浏览器)
将 HTML Form 元素作为 payload 传递,以将其作为 `multipart/form-data` 内容提交。
```
await axios.postForm(
"https://httpbin.org/post",
document.querySelector("#htmlForm"),
);
```
通过将 `Content-Type` 请求头显式设置为 `application/json`,`FormData` 和 `HTMLForm` 对象也可以作为 `JSON` 提交:
```
await axios.post(
"https://httpbin.org/post",
document.querySelector("#htmlForm"),
{
headers: {
"Content-Type": "application/json",
},
},
);
```
例如,表单
```
```
将作为以下 JSON 对象提交:
```
{
"foo": "1",
"deep": {
"prop": {
"spaced": "3"
}
},
"baz": [
"4",
"5"
],
"user": {
"age": "value2"
}
}
```
目前不支持将 `Blobs`/`Files` 作为 JSON (`base64`) 发送。
## 🆕 进度捕获
Axios 支持在浏览器和 Node 环境中捕获请求的上传/下载进度。
进度事件的频率被强制限制为每秒 `3` 次。
```
await axios.post(url, data, {
onUploadProgress: function (axiosProgressEvent) {
/*{
loaded: number;
total?: number;
progress?: number; // in range [0..1]
bytes: number; // how many bytes have been transferred since the last trigger (delta)
estimated?: number; // estimated time in seconds
rate?: number; // upload speed in bytes
upload: true; // upload sign
}*/
},
onDownloadProgress: function (axiosProgressEvent) {
/*{
loaded: number;
total?: number;
progress?: number;
bytes: number;
estimated?: number;
rate?: number; // download speed in bytes
download: true; // download sign
}*/
},
});
```
你也可以在 node.js 中跟踪流上传/下载进度:
```
const { data } = await axios.post(SERVER_URL, readableStream, {
onUploadProgress: ({ progress }) => {
console.log((progress * 100).toFixed(2));
},
headers: {
"Content-Length": contentLength,
},
maxRedirects: 0, // avoid buffering the entire stream
});
```
## 🆕 速率限制
下载和上传速率限制只能针对 http adapter(node.js)进行设置:
```
const { data } = await axios.post(LOCAL_SERVER_URL, myBuffer, {
onUploadProgress: ({ progress, rate }) => {
console.log(
`Upload [${(progress * 100).toFixed(2)}%]: ${(rate / 1024).toFixed(2)}KB/s`,
);
},
maxRate: [100 * 1024], // 100KB/s limit
});
```
## 🆕 AxiosHeaders
Axios 拥有自己的 `AxiosHeaders` 类,可以使用类似 Map 的 API 来操作请求头,从而保证大小写不敏感的工作方式。
尽管 HTTP 中的请求头是不区分大小写的,但 Axios 会出于样式原因以及在服务器错误地考虑请求头大小写时作为变通方法,保留原始请求头的大小写。
直接操作 headers 对象的旧方法仍然可用,但已弃用,不建议在未来使用。
### 操作请求头
一个 AxiosHeaders 对象实例可以包含不同类型的内部值。它们控制着设置和合并的逻辑。
最终具有字符串值的 headers 对象是由 Axios 调用 `toJSON` 方法获取的。
header 值可以是以下类型之一:
- `string` - 将被发送到服务器的普通字符串值
- `null` - 在渲染为 JSON 时跳过该 header
- `false` - 在渲染为 JSON 时跳过该 header,此外还表示必须使用设置为 `true` 的 `rewrite` 选项调用 `set` 方法
以覆盖此值(Axios 在内部使用它以允许用户选择不安装某些标头,如 `User-Agent` 或 `Content-Type`)
- `undefined` - 值未设置
headers 对象总是在拦截器和转换器内部初始化:
```
axios.interceptors.request.use((request: InternalAxiosRequestConfig) => {
request.headers.set("My-header", "value");
request.headers.set({
"My-set-header1": "my-set-value1",
"My-set-header2": "my-set-value2",
});
request.headers.set("User-Agent", false); // disable subsequent setting the header by Axios
request.headers.setContentType("text/plain");
request.headers["My-set-header2"] = "newValue"; // direct access is deprecated
return request;
});
```
你可以使用 `for...of` 语句遍历 `AxiosHeaders` 实例:
```
const headers = new AxiosHeaders({
foo: "1",
bar: "2",
baz: "3",
});
for (const [header, value] of headers) {
console.log(header, value);
}
// foo 1
// bar 2
// baz 3
```
### new AxiosHeaders(headers?)
构造一个新的 `AxiosHeaders` 实例。
```
constructor(headers?: RawAxiosHeaders | AxiosHeaders | string);
```
如果 headers 对象是一个字符串,它将被解析为 RAW HTTP 请求头。
```
const headers = new AxiosHeaders(`
Host: www.bing.com
User-Agent: curl/7.54.0
Accept: */*`);
console.log(headers);
// Object [AxiosHeaders] {
// host: 'www.bing.com',
// 'user-agent': 'curl/7.54.0',
// accept: '*/*'
// }
```
### AxiosHeaders#set
```
set(headerName, value: Axios, rewrite?: boolean);
set(headerName, value, rewrite?: (this: AxiosHeaders, value: string, name: string, headers: RawAxiosHeaders) => boolean);
set(headers?: RawAxiosHeaders | AxiosHeaders | string, rewrite?: boolean);
```
`rewrite` 参数控制覆盖行为:
- `false` - 如果 header 的值已设置(不是 `undefined`),则不覆盖
- `undefined`(默认)- 覆盖 header,除非其值被设置为 `false`
- `true` - 无论如何都覆盖
该选项还可以接受一个用户定义的函数,该函数决定是否应覆盖该值。
返回 `this`。
### AxiosHeaders#get(header)
```
get(headerName: string, matcher?: true | AxiosHeaderMatcher): AxiosHeaderValue;
get(headerName: string, parser: RegExp): RegExpExecArray | null;
```
返回 header 的内部值。它可以接受一个额外的参数,用于使用 `RegExp.exec`、
匹配器函数或内部键值解析器来解析 header 的值。
```
const headers = new AxiosHeaders({
"Content-Type": "multipart/form-data; boundary=Asrf456BGe4h",
});
console.log(headers.get("Content-Type"));
// multipart/form-data; boundary=Asrf456BGe4h
console.log(headers.get("Content-Type", true)); // parse key-value pairs from a string separated with \s,;= delimiters:
// [Object: null prototype] {
// 'multipart/form-data': undefined,
// boundary: 'Asrf456BGe4h'
// }
console.log(
headers.get("Content-Type", (value, name, headers) => {
return String(value).replace(/a/g, "ZZZ");
}),
);
// multipZZZrt/form-dZZZtZZZ; boundZZZry=Asrf456BGe4h
console.log(headers.get("Content-Type", /boundary=(\w+)/)?.[0]);
// boundary=Asrf456BGe4h
```
返回 header 的值。
### AxiosHeaders#has(header, matcher?)
```
has(header: string, matcher?: AxiosHeaderMatcher): boolean;
```
如果 header 已设置(没有 `undefined` 值),则返回 `true`。
### AxiosHeaders#delete(header, matcher?)
```
delete(header: string | string[], matcher?: AxiosHeaderMatcher): boolean;
```
如果至少移除了一个 header,则返回 `true`。
### AxiosHeaders#clear(matcher?)
```
clear(matcher?: AxiosHeaderMatcher): boolean;
```
移除所有 headers。
与 `delete` 方法的匹配器不同,这个可选的匹配器将用于匹配 header 的名称而不是值。
```
const headers = new AxiosHeaders({
foo: "1",
"x-foo": "2",
"x-bar": "3",
});
console.log(headers.clear(/^x-/)); // true
console.log(headers.toJSON()); // [Object: null prototype] { foo: '1' }
```
如果至少清除了一个 header,则返回 `true`。
### AxiosHeaders#normalize(format);
如果直接修改了 headers 对象,它可能会有同名但大小写不同的重复项。
此方法通过将重复的键合并为一个来规范化 headers 对象。
Axios 在调用每个拦截器之后会在内部使用此方法。
将 `format` 设置为 true,以便将 header 名称转换为小写并将首字母大写(`cOntEnt-type` => `Content-Type`)
```
const headers = new AxiosHeaders({
foo: "1",
});
headers.Foo = "2";
headers.FOO = "3";
console.log(headers.toJSON()); // [Object: null prototype] { foo: '1', Foo: '2', FOO: '3' }
console.log(headers.normalize().toJSON()); // [Object: null prototype] { foo: '3' }
console.log(headers.normalize(true).toJSON()); // [Object: null prototype] { Foo: '3' }
```
返回 `this`。
### AxiosHeaders#concat(...targets)
```
concat(...targets: Array): AxiosHeaders;
```
将实例与目标合并为一个新的 `AxiosHeaders` 实例。如果目标是字符串,它将被解析为 RAW HTTP 请求头。
返回一个新的 `AxiosHeaders` 实例。
### AxiosHeaders#toJSON(asStrings?)
将所有内部 header 值解析到一个新的 null 原型对象中。
将 `asStrings` 设置为 true,以便将数组解析为由逗号分隔的所有元素组成的字符串。
### AxiosHeaders.from(thing?)
```
from(thing?: AxiosHeaders | RawAxiosHeaders | string): AxiosHeaders;
```
返回一个根据传入的原始 headers 创建的新 `AxiosHeaders` 实例,
或者如果给定的 headers 对象已经是 `AxiosHeaders` 实例,则直接返回它。
### AxiosHeaders.concat(...targets)
```
concat(...targets: Array): AxiosHeaders;
```
返回一个通过合并目标对象创建的新 `AxiosHeaders` 实例。
### 快捷方式
可以使用以下快捷方法:
- `setContentType`、`getContentType`、`hasContentType`
- `setContentLength`、`getContentLength`、`hasContentLength`
- `setAccept`、`getAccept`、`hasAccept`
- `setUserAgent`、`getUserAgent`、`hasUserAgent`
- `setContentEncoding`、`getContentEncoding`、`hasContentEncoding`
## 🔥 Fetch adapter
Fetch adapter 是在 `v1.7.0` 中引入的。默认情况下,如果构建版本中不可用 `xhr` 和 `http` adapter,
或者环境不支持它们,则会使用它。
要将其作为默认使用,必须式选择它:
```
const { data } = axios.get(url, {
adapter: "fetch", // by default ['xhr', 'http', 'fetch']
});
```
你可以为此创建一个单独的实例:
```
const fetchAxios = axios.create({
adapter: "fetch",
});
const { data } = fetchAxios.get(url);
```
该 adapter 支持与 `xhr` adapter 相同的功能,**包括上传和下载进度捕获**。
此外,它还支持额外的响应类型,如 `stream` 和 `formdata`(如果环境支持)。
### 🔥 自定义 fetch
从 `v1.12.0` 开始,你可以自定义 fetch adapter 以使用自定义的 fetch API 代替环境全局对象。
你可以通过 env 配置传递自定义的 `fetch` 函数,`Request` 和 `Response` 构造函数。
这对于自定义环境和应用框架非常有帮助。
此外,在使用自定义 fetch 时,你可能还需要设置自定义的 Request 和 Response。如果不设置它们,将会使用全局对象。
如果你的自定义 fetch api 没有这些对象,并且全局对象与自定义 fetch 不兼容,
你必须通过传递 null 在 fetch adapter 内部禁用它们的使用。
基本示例:
```
import customFetchFunction from "customFetchModule";
const instance = axios.create({
adapter: "fetch",
onDownloadProgress(e) {
console.log("downloadProgress", e);
},
env: {
fetch: customFetchFunction,
Request: null, // undefined -> use the global constructor
Response: null,
},
});
```
#### 🔥 在 Tauri 中使用
在 [Tauri](https://tauri.app/plugin/http-client/) 应用中设置 Axios 以使用忽略请求 CORS 策略的平台 fetch 函数的最小示例。
```
import { fetch } from "@tauri-apps/plugin-http";
import axios from "axios";
const instance = axios.create({
adapter: "fetch",
onDownloadProgress(e) {
console.log("downloadProgress", e);
},
env: {
fetch,
},
});
const { data } = await instance.get("https://google.com");
```
#### 🔥 在 SvelteKit 中使用
[SvelteKit](https://svelte.dev/docs/kit/web-standards#Fetch-APIs) 框架具有用于服务器渲染(即所谓的 `load` 函数)的自定义 fetch 函数实现,并且也使用相对路径,
这使得它与标准的 URL API 不兼容。因此,必须将 Axios 配置为使用自定义 fetch API:
```
export async function load({ fetch }) {
const { data: post } = await axios.get(
"https://jsonplaceholder.typicode.com/posts/1",
{
adapter: "fetch",
env: {
fetch,
Request: null,
Response: null,
},
},
);
return { post };
}
```
## 🔥 HTTP2
在 `1.13.0` 版本中,向 `http` adapter 添加了实验性的 `HTTP2` 支持。
现在可以使用 `httpVersion` 选项来选择所使用的协议版本。
可以通过 `http2Options` 配置为内部 `session.request()` 调用传递额外的原生选项。
此配置还包括自定义的 `sessionTimeout` 参数,默认为 `1000ms`。
```
const form = new FormData();
form.append("foo", "123");
const { data, headers, status } = await axios.post(
"https://httpbin.org/post",
form,
{
httpVersion: 2,
http2Options: {
// rejectUnauthorized: false,
// sessionTimeout: 1000
},
onUploadProgress(e) {
console.log("upload progress", e);
},
onDownloadProgress(e) {
console.log("download progress", e);
},
responseType: "arraybuffer",
},
);
```
## Semver
自从 Axios 达到 `v.1.0.0` 以来,我们将完全遵循[此处](https://semver.org/)的规范拥抱 semver
## PromCDN
axios 依赖于原生 ES6 Promise 实现,并[支持](https://caniuse.com/promises)它。
如果你的环境不支持 ES6 Promises,你可以使用 [polyfill](https://github.com/jakearchibald/es6-promise)。
## axios API
axios 包含 [TypeScript](https://typescriptlang.org) 定义和 axios 错误的类型守卫。
```
let user: User = null;
try {
const { data } = await axios.get("/user?ID=12345");
user = data.userDetails;
} catch (error) {
if (axios.isAxiosError(error)) {
handleAxiosError(error);
} else {
handleUnexpectedError(error);
}
}
```
因为 axios 使用 ESM 默认导出和 CJS `module.exports` 进行双重发布,所以有一些注意事项。
推荐的设置是使用 `"moduleResolution": "node16"`(这是由 `"module": "node16"` 隐含的)。请注意,这需要 TypeScript 4.7 或更高版本。
如果你使用 ESM,你的设置应该没有问题。
如果你将 TypeScript 编译为 CJS 并且无法使用 `"moduleResolution": "node 16"`,则必须启用 `esModuleInterop`。
如果你使用 TypeScript 对 CJS JavaScript 代码进行类型检查,你唯一的选择是使用 `"moduleResolution": "node16"`。
你还可以创建一个带有类型化拦截器的自定义实例:
```
import axios, { AxiosInstance, InternalAxiosRequestConfig } from "axios";
const apiClient: AxiosInstance = axios.create({
baseURL: "https://api.example.com",
timeout: 10000,
});
apiClient.interceptors.request.use((config: InternalAxiosRequestConfig) => {
// Add auth token
return config;
});
```
## 在线一键设置
你可以使用 Gitpod,这是一个在线 IDE(对开源免费),用于在线贡献或运行示例。
[](https://gitpod.io/#https://github.com/axios/axios/blob/main/examples/server.js)
## 资源
- [更新日志](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [生态系统](https://github.com/axios/axios/blob/v1.x/ECOSYSTEM.md)
- [贡献指南](https://github.com/axios/axios/blob/v1.x/CONTRIBUTING.md)
- [行为准则](https://github.com/axios/axios/blob/v1.x/CODE_OF_CONDUCT.md)
## 致谢
axios 深受 [AngularJS](https://angularjs.org/) 提供的 [$http service](https://docs.angularjs.org/api/ng/service/$http) 的启发。最终,axios 旨在提供一个独立的、类似于 `$http` 的服务,以便在 AngularJS 外部使用。
## 许可证
[](LICENSE)