当我们构建需要我们向后端或第三方 API 发出网络请求的应用程序时,我们使用 Axios 和 Fetch 等 HTTP 客户端来执行此类请求。
在本指南中,我们介绍了 Axios 和 Fetch 并对它们进行比较,以便我们可以做出明智的决定来选择哪一个。
Fetch 和 Axios 的快速概览
Fetch API 是一个接口,它公开了一个fetch()为发出网络请求而调用的方法。它内置于现代浏览器中,因此无需安装。它也可以作为node.js 中的实验性功能使用。
Axios是一个基于浏览器提供的XMLHttpRequest接口的客户端HTTP API。一些开发人员更喜欢 Axios 而不是内置Fetch API,因为它易于使用。
我们可以通过内容分发网络或 CDN 将其添加到我们的项目中,或者通过包管理器(如 npm 或 yarn)安装它。Axios 可以在浏览器或 node.js 环境中运行。
Fetch 和 axios 都是基于 Promise 的 HTTP 客户端。这意味着当我们使用它们发出网络请求时,它们会返回一个可以解决或拒绝的承诺promise。
比较 Fetch 和 Axios 的功能
让我们从语法开始。
句法比较
Fetch 接受两个参数。第一个参数是我们要获取的资源的 URL。第二个是一个可选参数,它是一个包含用于发出请求的配置选项的对象。因此,语法是:
如果没有配置选项,请求将默认发出 GET 请求:
fetch(url)
使用配置选项,我们可以为请求定义一些自定义设置,包括:
fetch(url, { |
axios 语法类似,但有很多不同的调用方式:
axios(url, { |
我们还可以像这样附加 HTTP 方法:
axios.get(url, { |
与 fetch 方法一样,我们可以忽略 axios 中的 HTTP 方法,默认为 GET,如下所示:
axios(url)
同样,我们可以使用第二个参数为请求定义一些自定义设置:
axios(url, { |
我们也可以这样写:
axios({ |
现在让我们看看 Axios 和 fetch 处理响应的不同方式。
处理 JSON 数据
在下面的示例中,我们对名为 JSONPlaceholder的 REST API 执行 GET 请求,以使用 fetch 和 Axios 获取待办事项列表并比较差异。
使用 Fetch API,我们的代码如下所示:
const url = "https://jsonplaceholder.typicode.com/todos"; |
返回一个承诺,其fetch()响应由.then() 方法处理。此时,我们还没有我们需要的 JSON 数据格式,所以我们调用.json()响应对象上的方法。这将返回另一个使用 JSON 格式的数据解析的 promise。因此,典型的 fetch 请求包含两个.then()调用。
但是,如果我们使用 Axios 执行相同的 fetch,我们有以下代码:
const url = "https://jsonplaceholder.typicode.com/todos"; |
使用 Axios,响应数据默认以 JSON 格式提供。响应数据始终data在响应对象的属性上可用。
responseType我们可以通过在配置选项中指定 来覆盖默认的 JSON 数据类型,如下所示:
axios.get(url, { |
自动字符串化
现在让我们尝试使用JSONPlaceholder API 发送数据。
为此,我们需要将数据序列化为 JSON 字符串。当我们使用方法将 JavaScript 对象发送到 API POST 时,Axios 会自动对数据进行字符串化。
以下代码 post 使用 Axios 执行请求:
const url = "https://jsonplaceholder.typicode.com/todos"; |
当我们用axios发出一个post请求时,我们会把要发送的数据作为请求主体分配给data属性。我们还可以设置内容类型头。默认情况下,axios将Content-Type设置为application/json。
如果我们使用Fetch API,我们必须使用JSON.stringify()手动串联该对象,然后将其分配到我们的请求正文。
const url = "https://jsonplaceholder.typicode.com/todos"; |
我们还必须用Fetch明确地将Content-Type设置为application/json。
错误处理
fetch和axios都会返回一个被解决或拒绝的承诺。
当承诺被拒绝时,我们可以使用.catch()来处理这个错误。与Fetch方法相比,我们用axios处理错误的方式更加简洁。
从axios开始,用.catch()处理的典型错误是这样的。
const url = "https://jsonplaceholder.typicode.com/todos"; |
如果状态代码不在2xx的范围内,Axios的承诺将拒绝。我们可以通过检查err对象是否包含响应或请求属性来确定关于错误的更多信息,就像这样:
.catch((err) => { |
错误对象上的response 属性表示客户端收到了一个状态代码在2xx范围之外的错误响应。错误对象上的请求属性表明提出了一个请求,但客户端没有收到响应。否则,如果没有请求或响应属性,说明在设置网络请求时出现了错误。
如果我们得到一个404错误或任何其他的HTTP错误,Fetch不会拒绝一个承诺。Fetch只在网络失败时拒绝一个承诺。所以我们必须在.then子句中手动处理HTTP错误。
让我们看一下下面的代码。
const url = "https://jsonplaceholder.typicode.com/todos"; |
在响应块中,我们正在检查响应的ok状态是否为false,然后我们抛出一个自定义的错误,在.catch块中处理。
响应超时/取消请求
让我们看看这些HTTP客户端是如何处理HTTP请求的响应超时的。通过Axios,我们可以在配置对象中添加一个超时属性,并指定请求终止前的时间,单位为毫秒。
在下面的代码段中,我们的目的是在请求超过4秒时终止请求,然后在控制台记录一个错误。
const url = "https://jsonplaceholder.typicode.com/todos"; |
为了取消Fetch的请求,我们可以使用AbortController接口。请看下面的用法。
const url = "https://jsonplaceholder.typicode.com/todos"; |
我们首先创建了一个控制器对象,获得了对信号对象和abort()方法的访问权。然后我们通过配置选项将信号对象传递给fetch()。有了这个,只要调用abort方法,fetch请求就会终止。我们可以看到,在setTimeout函数的帮助下,如果服务器在4秒内没有回应,操作就会终止。
本地的Fetch比axios略快。这并不重要,因为两个客户端都是异步的。
Axios和Fetch在现代浏览器中被广泛支持。对于像IE 11这样不支持ES6 Promises的旧环境,我们必须使用一个polyfill。另外,特别是对于Fetch,我们将添加另一个polyfill来支持旧版浏览器的实现。