当前位置:首页 > 科技  > 软件

Axios vs. fetch():哪个最适合 HTTP 请求?

来源: 责编: 时间:2024-03-19 17:37:04 119观看
导读因为Axios的易于使用,所以有些开发人员比起内置的API,更喜欢Axios。但许多人高估了这个库。fetch() API不但完全能够重现Axios的关键功能,而且还有随时可用于所有现代浏览器中的独特优势。在本文中,我将按照基本语法、向

因为Axios的易于使用,所以有些开发人员比起内置的API,更喜欢Axios。gAZ28资讯网——每日最新资讯28at.com

但许多人高估了这个库。gAZ28资讯网——每日最新资讯28at.com

fetch() API不但完全能够重现Axios的关键功能,而且还有随时可用于所有现代浏览器中的独特优势。gAZ28资讯网——每日最新资讯28at.com

在本文中,我将按照基本语法、向后兼容性、响应超时、自动JSON数据转换、HTTP拦截器、下载进度、同时请求这些方面来比较fetch()和Axios,看看它们如何执行任务。gAZ28资讯网——每日最新资讯28at.com

希望在本文结束时,大家对这两个API有了更深入的了解。gAZ28资讯网——每日最新资讯28at.com

基本语法

在我们深入研究Axios更高级地功能之前,先与fetch()进行基本语法的比较。gAZ28资讯网——每日最新资讯28at.com

下面是Axios如何将带有自定义请求头的[POST]请求发送到指定URL的代码:gAZ28资讯网——每日最新资讯28at.com

// axiosconst url = 'https://jsonplaceholder.typicode.com/posts'const data = {  a: 10,  b: 20,};axios  .post(url, data, {    headers: {      Accept: "application/json",      "Content-Type": "application/json;charset=UTF-8",    },  })  .then(({data}) => {    console.log(data);});

与fetch()版本进行比较:gAZ28资讯网——每日最新资讯28at.com

// fetch()const url = "https://jsonplaceholder.typicode.com/todos";const options = {  method: "POST",  headers: {    Accept: "application/json",    "Content-Type": "application/json;charset=UTF-8",  },  body: JSON.stringify({    a: 10,    b: 20,  }),};fetch(url, options)  .then((response) => response.json())  .then((data) => {    console.log(data);  });

注意:gAZ28资讯网——每日最新资讯28at.com

  • 为发送数据,fetch()使用body属性将数据发送到服务端,而Axios使用data属性
  • fetch()中的数据使用JSON.stringify方法转换为字符串
  • Axios自动转换从服务器返回的数据,但使用fetch()时,你必须调用response.json方法将数据解析为JavaScript对象。
  • 使用Axios,服务器提供的数据响应可以在数据对象中访问,而对于fetch()方法,最终数据可以命名为任何变量

向后兼容性

Axios的主要卖点之一是其广泛的浏览器支持。gAZ28资讯网——每日最新资讯28at.com

即使是像IE11这样的旧浏览器也可以毫无问题地运行Axios。这是因为它背后使用了XMLHttpRequest。gAZ28资讯网——每日最新资讯28at.com

而fetch()仅支持Chrome 42+,Firefox 39+,Edge 14+和Safari 10.3+。gAZ28资讯网——每日最新资讯28at.com

如果你使用Axios的唯一原因是向后兼容性,那么实际上并不需要HTTP库。而且,你可以将fetch()与polyfill一起使用,在不支持fetch()的web浏览器上实现类似的功能。gAZ28资讯网——每日最新资讯28at.com

要使用fetch() polyfill,可以通过npm命令进行安装,如下所示:gAZ28资讯网——每日最新资讯28at.com

npm install whatwg-fetch --save

然后,提出如下请求:gAZ28资讯网——每日最新资讯28at.com

import 'whatwg-fetch'window.fetch(...)

谨记,在有些旧浏览器中,可能还需要promise polyfill。gAZ28资讯网——每日最新资讯28at.com

响应超时

在Axios中设置超时的简单性,是一些开发人员比fetch()更喜欢Axios的原因之一。gAZ28资讯网——每日最新资讯28at.com

在Axios中,你可以使用配置对象的timeout属性来设置请求中止之前的毫秒数。gAZ28资讯网——每日最新资讯28at.com

例如:gAZ28资讯网——每日最新资讯28at.com

axios({  method: 'post',  url: '/login',  timeout: 4000,    // 4 seconds timeout  data: {    firstName: 'David',    lastName: 'Pollock'  }}).then(response => {/* handle the response */}).catch(error => console.error('timeout exceeded'))

Fetch()通过AbortController接口提供类似的功能。gAZ28资讯网——每日最新资讯28at.com

不过,它的代码不如Axios版本简单:gAZ28资讯网——每日最新资讯28at.com

const controller = new AbortController();const options = {  method: 'POST',  signal: controller.signal,  body: JSON.stringify({    firstName: 'David',    lastName: 'Pollock'  })};  const promise = fetch('/login', options);const timeoutId = setTimeout(() => controller.abort(), 4000);promise  .then(response => {/* handle the response */})  .catch(error => console.error('timeout exceeded'));

代码使用AbortController.abort()构造函数创建AbortController对象,它允许我们稍后中止请求。gAZ28资讯网——每日最新资讯28at.com

Signal是AbortController的只读属性,提供了一种与请求通信或中止请求的方法。gAZ28资讯网——每日最新资讯28at.com

如果服务器在4秒内没有响应,则调用controller.abort(),终止操作。gAZ28资讯网——每日最新资讯28at.com

自动JSON数据转换

如前所述,Axios在发送请求时会自动字符串化数据(当然你也可以覆盖默认行为并定义不同的转换机制)。gAZ28资讯网——每日最新资讯28at.com

但是,当使用fetch()时,你必须手动执行此操作。gAZ28资讯网——每日最新资讯28at.com

比较:gAZ28资讯网——每日最新资讯28at.com

// axiosaxios.get('https://api.github.com/orgs/axios')  .then(response => {    console.log(response.data);  }, error => {    console.log(error);  });
// fetch()fetch('https://api.github.com/orgs/axios')  .then(response => response.json())    // one extra step  .then(data => {    console.log(data)   })  .catch(error => console.error(error));

自动转换数据是一个不错的功能,但同样,这不是你不能用fetch()做的事情。gAZ28资讯网——每日最新资讯28at.com

HTTP拦截器

Axios的主要功能之一是它能够拦截HTTP请求。gAZ28资讯网——每日最新资讯28at.com

当你需要检查或更改从应用程序到服务器的HTTP请求时,使用HTTP拦截器非常方便,从服务器到应用程序亦是如此(例如,日志记录、身份验证或重试失败的HTTP请求)。gAZ28资讯网——每日最新资讯28at.com

使用拦截器就不必为每个HTTP请求编写单独的代码。gAZ28资讯网——每日最新资讯28at.com

在你想要为处理请求和响应设置全局策略时,HTTP拦截器非常有用。gAZ28资讯网——每日最新资讯28at.com

以下是在Axios中声明请求拦截器的方法:gAZ28资讯网——每日最新资讯28at.com

axios.interceptors.request.use(config => {  // log a message before any HTTP request is sent  console.log('Request was sent');  return config;});// sent a GET requestaxios.get('https://api.github.com/users/sideshowbarker')  .then(response => {    console.log(response.data);  });

上面的代码中,axios.interceptors.request.use()方法用于定义发送HTTP请求之前要运行的代码。而axios.interceptors.response.use()用于拦截来自服务器的响应。gAZ28资讯网——每日最新资讯28at.com

假设存在网络错误,那么通过响应侦听器,可以重试相同的请求。gAZ28资讯网——每日最新资讯28at.com

默认情况下,fetch()不提供拦截请求的方法,但它的解决方法也并不复杂。gAZ28资讯网——每日最新资讯28at.com

那就是覆盖全局fetch()方法并定义自己的拦截器,如下所示:gAZ28资讯网——每日最新资讯28at.com

fetch = (originalFetch => {  return (...arguments) => {    const result = originalFetch.apply(this, arguments);      return result.then(console.log('Request was sent'));  };})(fetch);fetch('https://api.github.com/orgs/axios')  .then(response => response.json())  .then(data => {    console.log(data)   });

下载进度

进度条在加载时非常有用,尤其是对于互联网速度较慢的用户。gAZ28资讯网——每日最新资讯28at.com

以前,JavaScript程序员使用XMLHttpRequest.onprogress回调处理程序来实现进度指示器。gAZ28资讯网——每日最新资讯28at.com

Fetch API没有onprogress处理程序。事实上,它通过响应对象的body属性来提供ReadableStream的实例。gAZ28资讯网——每日最新资讯28at.com

以下示例表明如何使用ReadableStream在图像下载期间为用户提供即时反馈:gAZ28资讯网——每日最新资讯28at.com

index.html<!-- Wherever you html is -->  <div id="progress" src="">progress</div>  <img id="img">script.js'use strict'const element = document.getElementById('progress');fetch('https://fetch-progress.anthum.com/30kbps/images/sunrise-baseline.jpg')  .then(response => {    if (!response.ok) {      throw Error(response.status+' '+response.statusText)    }    // ensure ReadableStream is supported    if (!response.body) {      throw Error('ReadableStream not yet supported in this browser.')    }    // store the size of the entity-body, in bytes    const contentLength = response.headers.get('content-length');    // ensure contentLength is available    if (!contentLength) {      throw Error('Content-Length response header unavailable');    }    // parse the integer into a base-10 number    const total = parseInt(contentLength, 10);    let loaded = 0;    return new Response(      // create and return a readable stream      new ReadableStream({        start(controller) {          const reader = response.body.getReader();          read();          function read() {            reader.read().then(({done, value}) => {              if (done) {                controller.close();                return;               }              loaded += value.byteLength;              progress({loaded, total})              controller.enqueue(value);              read();            }).catch(error => {              console.error(error);              controller.error(error)                              })          }        }      })    );  })  .then(response =>     // construct a blob from the data    response.blob()  )  .then(data => {    // insert the downloaded image into the page    document.getElementById('img').src = URL.createObjectURL(data);  })  .catch(error => {    console.error(error);  })function progress({loaded, total}) {  element.innerHTML = Math.round(loaded/total*100)+'%';}

在Axios中实现进度指示器更简单,尤其是在使用Axios进度条模块时。gAZ28资讯网——每日最新资讯28at.com

首先,包含以下样式和脚本:gAZ28资讯网——每日最新资讯28at.com

// the head of your HTML    <link rel="stylesheet" type="text/css"        href="https://cdn.rawgit.com/rikmms/progress-bar-4-axios/0a3acf92/dist/nprogress.css" />// the body of your HTML     <img id="img" />    <button onclick="downloadFile()">Get Resource</button>    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>    <script src="https://cdn.rawgit.com/rikmms/progress-bar-4-axios/0a3acf92/dist/index.js"></script>// add the following to customize the style<style>    #nprogress .bar {        background: red !important;    }    #nprogress .peg {        box-shadow: 0 0 10px red, 0 0 5px red !important;    }    #nprogress .spinner-icon {        border-top-color: red !important;        border-left-color: red !important;    }</style>

然后像这样实现进度条:gAZ28资讯网——每日最新资讯28at.com

<script type="text/javascript">        loadProgressBar();        function downloadFile() {          getRequest(            "https://fetch-progress.anthum.com/30kbps/images/sunrise-baseline.jpg"          );        }        function getRequest(url) {          axios            .get(url, { responseType: "blob" })            .then(function (response) {              const reader = new window.FileReader();              reader.readAsDataURL(response.data);              reader.onload = () => {                document.getElementById("img").setAttribute("src", reader.result);              };            })            .catch(function (error) {              console.log(error);            });        }      </script>

代码使用FileReaderAPI异步读取下载的图像。gAZ28资讯网——每日最新资讯28at.com

readAsDataURL方法以Base64编码字符串的形式返回图像的数据,然后将其插入到img标记的src属性中以显示图像。gAZ28资讯网——每日最新资讯28at.com

并发请求

为了同时发出多个请求,Axios提供axios.all()方法。gAZ28资讯网——每日最新资讯28at.com

只需将请求数组传递给此方法,然后使用axios.spread()将响应数组的属性分配给单独的变量:gAZ28资讯网——每日最新资讯28at.com

axios.all([  axios.get('https://api.github.com/users/iliakan'),   axios.get('https://api.github.com/users/taylorotwell')]).then(axios.spread((obj1, obj2) => {  // Both requests are now complete  console.log(obj1.data.login + ' has ' + obj1.data.public_repos + ' public repos on GitHub');  console.log(obj2.data.login + ' has ' + obj2.data.public_repos + ' public repos on GitHub');}));

也可以使用内置的Promise.all()方法获得相同的结果。gAZ28资讯网——每日最新资讯28at.com

将所有fetch请求作为数组传递给Promise.all()。接着使用async函数处理响应,如下所示:gAZ28资讯网——每日最新资讯28at.com

Promise.all([  fetch('https://api.github.com/users/iliakan'),  fetch('https://api.github.com/users/taylorotwell')]).then(async([res1, res2]) => {  const a = await res1.json();  const b = await res2.json();  console.log(a.login + ' has ' + a.public_repos + ' public repos on GitHub');  console.log(b.login + ' has ' + b.public_repos + ' public repos on GitHub');}).catch(error => {  console.log(error);});

结论

Axios在紧凑的软件包中提供了一个易于使用的API,可满足大多数HTTP通信需求。gAZ28资讯网——每日最新资讯28at.com

而web浏览器提供的fetch()方法则能完全重现Axios库的主要功能。gAZ28资讯网——每日最新资讯28at.com

所以,是否加载客户端HTTP API取决于你是否习惯使用内置API。gAZ28资讯网——每日最新资讯28at.com

编程快乐!gAZ28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-77835-0.htmlAxios vs. fetch():哪个最适合 HTTP 请求?

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: Go语言实现自动HTTPS的快速、灵活的Web服务器

下一篇: 印度“硅谷”班加罗尔面临缺水危机,科技企业另觅他处

标签:
  • 热门焦点
Top