Fetch vs Axios
原文链接:https://meticulous.ai/blog/fetch-vs-axios/[1]
作者:Ibas Majid[2]
正文从这开始~
当我们构建的应用程序需要我们进行网络请求时,无论是对我们的后端还是对第三方API,我们都使用Axios和Fetch这样的HTTP客户端来执行此类请求。
在本篇指南中,我们将会介绍Axios和Fetch,并对它们进行比较,以便让我们做出明智的决定去选择。
快速概览
Fetch API是一个接口,暴露了一个叫做fetch()
的方法,用于发出网络请求。它内置于现代浏览器中,因此不需要安装。它也可以作为node.js
的一个实验性功能使用。
Axios是一个第三方库,我们可以通过CDN将其添加到我们的项目中,也可以通过包管理器来安装,比如说npm
或者yarn
。Axios可以运行在浏览器或者node.js
环境中。
Fetch和Axios都是基于promise
的HTTP客户端。这意味着当我们使用它们来创建网络请求时,它们会返回一个resolve
或者reject
的promise
。
安装Axios
如果我们在node.js
环境中使用axios
,我们可以使用以下的安装方法:
使用NPM安装:
npm install axios
使用Yarn安装:
yarn add axios
将它们导入到项目中:
import axios from "axios";
如果我们在浏览器中使用Axios,可以使用CDN引入:
<script src="<https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js>"></script>
你可以在这里[3]阅读所有安装Axios的方式。现在一切准备就绪,接下来开始比较它们。
比较Fetch和Axios的特性
让我们从语法开始。
语法
Fetch接收两个参数。第一个参数是我们要获取的资源的URL。第二个参数是可选参数,它是一个对象,包含发出请求的配置项。基于此,具体语法如下:
如果没有指定配置项,会默认发出GET请求:
fetch(url)
如果指定配置项,我们可以为请求定义一些自定义设置,包括:
fetch(url, {
method: 'GET', // other options: POST, PUT, DELETE, etc.
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({}),
})
Axios的语法更加简洁,但是有很多不同的调用方式:
axios(url, {
// configuration options
})
我们也可以像这样来附加HTTP方法:
axios.get(url, {
// configuration options
})
和fetch方法一样,我们也可以忽略axios中的HTTP方法,默认为GET,就像这样:
axios(url)
同样地,我们可以使用第二个参数,为请求定义一些自定义设置:
axios(url, {
method: 'get', // other options: post, put, delete, etc.
headers: {},
data: {},
})
也可以这么写:
axios({
method: 'get',
url: url,
headers: {},
data: {},
})
现在让我们下研究Axios和fetch处理响应的不同方式。
处理JSON数据
在下面的例子中,我们对一个名为JSONPlaceholder
的REST API执行了一个GET请求。使用fetch和Axios获取待办事项列表,并比较两者的差异。
使用Fetch API,我们的代码如下所示:
const url = "<https://jsonplaceholder.typicode.com/todos>";
fetch(url)
.then(response => response.json())
.then(console.log);
在控制台中打印的结果如下所示:
fetch结果.png
fetch()
返回了一个promise
,其响应由.then()
方法来处理。此时,我们没有得到我们所需要的JSON数据格式,因此,我们对响应对象调用.json()
方法。这将返回另一个promise
,该promise
用JSON形式来解决(resolved)数据。所以一个典型的fetch请求包含两个.then()
调用。
然而,如果我们使用axios来执行相同的数据获取,我们会有以下代码:
const url = "<https://jsonplaceholder.typicode.com/todos>";
axios.get(url)
.then(response => console.log(response.data));
在Axios中,响应数据默认为JSON。响应数据始终在响应对象的data
属性上可用。
我们可以通过在配置项中指定responseType
,来覆盖默认的JSON数据类型,就像这样:
axios.get(url, {
responseType: 'json' // options: 'arraybuffer', 'document', 'blob', 'text', 'stream'
})
自动字符串化
现在,让我们试着使用JSONPlaceholder[4] API来发送数据。
我们需要序列化我们的数据到JSON字符串中。当我们使用POST
方法将JS对象发送到API,Axios会自动将数据字符串化。
以下代码使用Axios来执行一个post
请求:
const url = "<https://jsonplaceholder.typicode.com/todos>";
const todo = {
title: "A new todo",
completed: false
}
axios.post(url, {
headers: {
'Content-Type': 'application/json',
},
data: todo
})
.then(console.log);
当我们使用axios来发送post
请求,我们把要发送的数据作为请求体分配给data
属性。我们也可以设置Content-Type
头部。默认情况下,axios设置Content-Type
值为application/json
。
让我们瞧一瞧响应对象:
axios响应对象.png
响应数据位于response.data
,就像这样:
.then(response => console.log(response.data));
如果我们使用Fetch API,我们必须手动调用JSON.stringify()
来字符串化对象。然后将其赋值到请求对象的data
属性上。
const url = "<https://jsonplaceholder.typicode.com/todos>";
const todo = {
title: "A new todo",
completed: false
};
fetch(url, {
method: "post",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(todo)
})
.then((response) => response.json())
.then((data) => console.log(data))
使用Fetch,我们还必须显式地设置Content-Type
值为application/json
。
错误处理
fetch和axios都返回一个被解决(resolved)或被拒绝(rejected)的promise
。当promise
被拒绝时,我们可以使用.catch()
来处理错误。与Fetch的方法相比,使用axios处理错误的方式更简洁。
从axios开始,使用.catch()
来处理典型错误。代码如下所示:
const url = "<https://jsonplaceholder.typicode.com/todos>";
axios.get(url)
.then((response) => console.log(response.data))
.catch((err) => {
console.log(err.message);
});
如果状态码超出2xx的范围,Axios的promise
将会拒绝(reject)。我们可以通过检查err
对象是否包含response
或request
属性来确定关于错误的更多信息。比如说:
.catch((err) => {
// handling error
if (err.response) {
// Request made and server responded
const { status, config } = err.response;
if (status === 404) {
console.log(`${config.url} not found`);
}
if (status === 500) {
console.log("Server error");
}
} else if (err.request) {
// Request made but no response from server
console.log("Error", err.message);
} else {
// some other errors
console.log("Error", err.message);
}
});
error
对象上的response
属性表示客户端收到了一个状态代码在2xx范围之外的错误响应。error对象上的request
属性表示发出了一个请求,但客户端没有收到响应。否则,如果没有response
或request
属性,则表示在设置网络请求时发生错误。
如果我们收到404错误或任何其他HTTP错误,Fetch将不会拒绝一个promise
。Fetch只有在网络请求失败时拒绝promise
。所以我们必须在.then
子句中手动处理HTTP错误。
让我们瞧一瞧下面代码:
const url = "<https://jsonplaceholder.typicode.com/todos>";
fetch(url)
.then((response) => {
if (!response.ok) {
throw new Error(
`This is an HTTP error: The status is ${response.status}`
);
}
return response.json();
})
.then(console.log)
.catch(err => {
console.log(err.message);
});
在response
代码块中,我们检查了response
的ok
属性是否是false
,然后我们抛出了一个自定义错误,并在.catch
代码块中进行处理。
我们可以像这样查看响应对象上可用的方法:
.then(console.log)
响应对象可用方法.png
上面的截图是一个成功的fetch。在我们碰到一个错误的URL端点的情况下,ok
和status
属性将分别变成false
和404
,然后我们抛出一个错误,.catch()
子句将显示我们自定义的错误信息。
响应超时/取消请求
让我们看看HTTP客户端针对HTTP请求,如何处理响应超时。对于Axios,我们可以在配置对象中添加一个timeout
属性,并指定请求终止前的时间,单位为毫秒。
在下面的代码片段中,我们的目标是在请求时间超过4秒时终止请求,然后在控制台中打印一个错误。
const url = "<https://jsonplaceholder.typicode.com/todos>";
axios.get(url, {
timeout: 4000, // default is `0` (no timeout)
})
.then((response) => console.log(response.data))
.catch((err) => {
console.log(err.message);
});
在Fetch中取消请求,我们可以使用AbortController[5]接口。参考下面的用法:
const url = "<https://jsonplaceholder.typicode.com/todos>";
const controller = new AbortController();
const signal = controller.signal;
setTimeout(() => controller.abort(), 4000);
fetch(url, {
signal: signal
})
.then((response) => response.json())
.then(console.log)
.catch((err) => {
console.error(err.message);
});
我们首先创建了一个controller
对象,获得了对signal
对象和abort()
方法的访问权。然后通过配置选项将signal
对象传递给fetch()
。有了上述配置,只要调用abort
方法,fetch请求就会终止。正如我们看到的,在setTimeout
函数的帮助下,如果服务器在4秒内没有响应,fetch操作就会终止。
性能
既然两者都是基于promise
的,那么他们不应引起任何性能问题。然而,我们仍然可以使用measurethat.net[6]来衡量它们的性能。
在使用在线工具进行连续测试后,我们得到如下结果:
性能测试.png
如上所述,原生Fetch比axios略快。这是无关紧要的,因为两个客户端都是异步的。
浏览器支持
Axios和Fetch在现代浏览器中得到广泛支持。对于较老环境比如IE11,不支持ES6 Promise语法。我们必须使用polyfill[7]来解决兼容性问题。特别是Fetch,我们将添加另一个polyfill[8]来支持在旧浏览器[9]中的实现。
总结
在本指南中,我们讨论了Fetch和axios,并在实际场景中对它们进行了比较。最后,你在项目中选择什么取决于你的个人偏好和易用性。
参考资料
[1]
https://meticulous.ai/blog/fetch-vs-axios/: https://meticulous.ai/blog/fetch-vs-axios/
[2]
Ibas Majid: https://ibaslogic.com/
[3]
这里: https://axios-http.com/docs/intro
[4]
JSONPlaceholder: https://jsonplaceholder.typicode.com/
[5]
AbortController: https://developer.mozilla.org/en-US/docs/Web/API/AbortController
[6]
measurethat.net: https://www.measurethat.net/
[7]
使用polyfill: https://github.com/stefanpenner/es6-promise
[8]
添加另一个polyfill: https://github.com/github/fetch
[9]
旧浏览器: https://caniuse.com/fetch
相关文章
- 一文吃透 VS Code+Git 操作(vs code中git的相关配置与使用)
- VS code安装和使用技巧
- 免费开源的 VS Code 被倒卖?微软和谷歌看了都傻眼...
- 使用VS连接 SQL Server数据库的简单指南(vs连接sqlserver)
- MySQL vs Oracle: 对比两种数据库系统(mysql与oracle区别)
- VS如何连接MySQL数据库(vs怎么连接mysql)
- 比较 VS Code 与 SQL Server 的性能(vssqlserver)
- 2021 全球开发者报告:VS Code 环境占绝对优势,编程语言 JS 最流行 Rust 最受喜爱 Clojure 最赚钱
- 开源 vs. 闭源
- VS一键连接MySQL,数据库管理如此便捷(vs连接mysql)
- 搭建VS之旅:配置MySQL(vs配置mysql)
- VS如何进行远程调试Linux:详细指南(vs远程调试linux)
- VS与SQL Server的强强联合:提供更全面的数据应用能力(vs跟sqlserver)
- VS联与SQL Server 配合协作,让工作更轻松。(vs联sqlserver)
- VS 开发 SQL Server 数据库应用实践(vs的sqlserver)
- VS与SqlServer联手构建可靠的数据库运行环境(SqlServer和vs)
- 数据库利用Axios调用MySQL数据库新的数据接口方式(axios请求mysql)
- Redis VS 内存 一场谁为赢家的你我争锋(放Redis还是内存)
- VS操作Redis 简单而不繁琐(在vs操作redis)
- VS中如何优雅地操作Redis(vs操作redis)
- 调试Javascript代码(浏览器F12及VS中debugger关键字)