Axios或fetch()应该使用哪个?

Axios或fetch()应该使用哪个?

现在相信有很多前端开发人员在用Axios库,它的好处用过的人都知道。但是,必须认识到Axios并非始终是理想的解决方案,并且有时会有更好的选择来发出HTTP请求。

毫无疑问,与内置API相比,某些前端开发人员更喜欢Axios,因为它易于使用。但是许多人高估了对这样一个库的需求。该fetch() API完全能够重现Axios的关键功能,并且具有在所有现代浏览器中均可轻松获得的附加优势。

在本文中,我们将比较fetch()和Axios,看看如何将它们用于执行不同的任务。希望到本文结尾,大家将对这两个API有更好的了解。

基本语法

在深入研究Axios的更高级功能之前,我们先将其基本语法与fetch()进行比较。这是使用Axios将POST带有自定义标头的请求发送到URL的方法。Axios会自动将数据转换为JSON,因此您不必这样做。

// axios
const options = {
  url: 'http://localhost/test.htm',
  method: 'POST',
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json;charset=UTF-8'
  },
  data: {
    a: 10,
    b: 20
  }
};

axios(options).then(response = >{
  console.log(response.status);
});

现在,将此代码与fetch()版本相比较,产生相同的结果:

// fetch()
const url = 'http://localhost/test.htm';
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 = >{
  console.log(response.status);
});

注意:

  • 要发送数据,fetch()使用body属性,而Axios使用data属性。
  • fetch()中输入的数据被字符串化。
  • 该URL作为参数传递给fetch()。但是,在Axios中,URL是在options对象中设置的。

向后兼容

Axios的主要优点之一是其广泛的浏览器支持。即使是像IE11这样的旧版浏览器,也可以毫无问题地运行Axios。另一方面,仅支持Chrome 42+,Firefox 39+,Edge 14+和Safari 10.1+

axios兼容性表

如果你使用Axios的唯一原因是向后兼容,那么你实际上就不需要HTTP库。取而代之的是,你可以使用这种类似的polyfill在不支持的网络浏览器上实现类似的功能。要开始使用fetch() polyfill,请通过npm命令安装它:

npm install whatwg-fetch --save

然后,我们可以发出如下请求:

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

注意,在某些旧的浏览器中,您可能还需要promise填充。

响应超时

另外,在Axios中设置timeout要比在fetch()设置更加简单,这也是某些前端开发人员偏爱它的原因之一。在Axios中,你可以使用config对象中的可选timeout属性设置请求中止前的毫秒数。例如:

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

Fetch()通过AbortController界面提供类似的功能。但是,它不像Axios版本那么简单:

const controller = new AbortController();
const options = {
  method: 'POST',
  signal: controller.signal,
  body: JSON.stringify({
    firstName: 'mybj',
    lastName: 'qdbk'
  })
};
const promise = fetch('/login', options);
const timeoutId = setTimeout(() = >controller.abort(), 4000);

promise.then(response = >{
  /* handle the response */
}).
catch(error = >console.error('timeout exceeded'));

在这里,我们使用AbortController.AbortController()构造函数创建一个AbortController对象,该对象允许我们稍后中止请求。signal是提供一种与请求进行通信或中止请求的方式的只读属性。如果服务器在不到四秒钟内没有响应,controller.abort()则将被调用,并且操作将终止。

自动转换JSON数据

如前所述,Axios在发送请求时自动对数据进行字符串化(尽管你可以覆盖默认行为并定义不同的转换机制)。但是,在使用fetch()时,必须手动执行。

// axios
axios.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()不能做的事情。

HTTP拦截器

Axios的主要功能之一是它能够拦截HTTP请求。当我们需要检查或更改从应用程序到服务器的HTTP请求(反之亦然)(例如,日志记录,身份验证等)时,HTTP拦截器会派上用场。使用拦截器,你不必为每个HTTP请求编写单独的代码。

在Axios中声明请求拦截器的方法如下:

axios.interceptors.request.use(config = >{
  // log a message before any HTTP request is sent
  console.log('Request was sent');

  return config;
});

// sent a GET request
axios.get('https://api.github.com/users/sideshowbarker')
  .then(response = >{
    console.log(response.data);
});

在此代码中,该axios.interceptors.request.use()方法用于定义要在发送HTTP请求之前运行的代码。

默认情况下,fetch()没有提供拦截请求的方法,但要想出一个解决办法并不难。您可以覆盖全局获取方法并定义自己的截取器,如:

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)
});

下载进度

加载大型资产时,进度指示器非常有用,尤其是对于互联网速度较慢的用户而言。以前,前端开发人员使用XMLHttpRequest.onprogress实现进度指示器的回调处理程序。

Fetch() API没有onprogress处理程序。相反,它通过响应对象的body属性提供ReadableStream实例。

以下示例演示了如何使用ReadableStream在图像下载期间为用户提供即时反馈:

// original code: https://github .com/AnthumChris/fetch-progress-indicators
< div id = "progress"src = "" > progress < /div>
<img id="img">

<script>

'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)+' % ';
}
</script>'

在Axios中实现进度指示器更简单,尤其是使用Axios进度条模块时。首先,您需要包含以下样式和脚本:

<link rel="stylesheet" type="text/css" href="https://cdn.rawgit.com/rikmms/progress-bar-4-axios/0a3acf92/dist/nprogress.css" />

<script src="https://cdn.rawgit.com/rikmms/progress-bar-4-axios/0a3acf92/dist/index.js"></script>

然后,你可以像这样实现进度条:

< img id = "img" >

<script >

loadProgressBar();

const url = 'https://fetch-progress.anthum.com/30kbps/images/sunrise-baseline.jpg';

function downloadFile(url) {
  axios.get(url, {
    responseType: 'blob'
  }).then(response = >{
    const reader = new window.FileReader();
    reader.readAsDataURL(response.data);
    reader.onload = () = >{
      document.getElementById('img').setAttribute('src', reader.result);
    }
  }).
  catch(error = >{
    console.log(error)
  });
}

downloadFile(url);
< /script>/

此代码使用FileReaderAPI异步读取下载的图像。该readAsDataURL方法以Base64编码的字符串形式返回图像的数据,然后将其插入img标签的src属性中以显示图像。

同时请求

为了同时发出多个请求,Axios提供了axios.all()方法。只需将请求数组传递给此方法,然后使用axios.spread()即可将响应数组的属性分配给单独的变量:

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()方法实现相同的结果。将所有提取请求作为数组传递给Promise.all()。接下来,使用async函数处理响应:

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通信需求。但是,如果您喜欢使用本机api,那么没有什么可以阻止你实现Axios特性。

如本文所述,完全有可能使用Web浏览器提供的fetch()方法来重现Axios库的关键功能。最终,是否值得加载客户端HTTP API取决于您是否对使用内置API感到满意。

原文作者:Faraz Kelhini

原文链接:Axios or fetch(): Which should you use?

翻译:码云笔记

1. 本站所有免费资源来源于用户上传和网络,因此不包含技术服务请大家谅解!如有侵权请邮件联系客服!
2. 本站不保证所提供下载的免费资源的准确性、安全性和完整性,免费资源仅供下载学习之用!如有链接无法下载、失效,请联系客服处理!
3. 您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容资源!如用于商业或者非法用途,与本站无关,一切后果请用户自负!
4. 如果您也有好的资源或技术教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
5. 加入前端开发QQ群:565733884,我们大家一起来交流技术!
码云笔记 » Axios或fetch()应该使用哪个?

发表评论

提供最优质的资源集合

立即查看 了解详情