当前位置:   article > 正文

Fetch、Axios、Ajax 的理解_fetch、ajax、axios

fetch、ajax、axios

一、 基本概念


Fetch、Axios、Ajax 都是前端用于发送HTTP请求的工具或技术:

  • Fetch:一种现代化的网络请求方法,通过使用 Promise 处理异步操作,简洁而直观地发送HTTP请求、处理响应,并支持各种功能和API,如设置请求头、传递参数、处理流数据、上传下载文件等。
  • Axios:一个基于Promise的现代化HTTP客户端,是目前最流行的 HTTP 客户端,可以在浏览器和Node.js环境中发送HTTP请求,并具有拦截请求和响应、支持并发请求、提供丰富的API等功能。
  • Ajax:通过在浏览器和服务器之间进行异步通信,实现部分页面更新和动态交互,提升用户体验;可以在不重新加载整个页面的情况下,通过JavaScript发送HTTP请求到服务器,并处理服务器返回的数据;减少带宽消耗,提高页面加载速度;提高用户交互性,实现更多的动态效果和实时更新。

详情

AJAX

AJAX(Asynchronous JavaScript and XML,异步 JavaScript 和 XML)是一种使用现有的网页技术来创建异步请求和更新页面内容的方法。Ajax 本身不是一种技术,而是一种将一些现有技术结合起来使用的方法,包括:HTML 或 XHTML、CSS、JavaScript、DOM、XML、XSLT、以及最重要的 XMLHttpRequest 对象。

当使用结合了这些技术的 Ajax 模型以后,网页应用能够快速地将增量更新呈现在用户界面上,而不需要重载(刷新)整个页面。这使得程序能够更快地回应用户的操作。Ajax 最吸引人的特性是它的“异步”性质,这意味着它可以与服务器通信、交换数据并更新页面,而无需刷新页面。

Ajax 是一种使用浏览器提供的 XMLHttpRequest 对象实现的技术,用于在不刷新整个页面的情况下进行异步请求和更新页面内容。可以说 Ajax 是基于浏览器提供的 XMLHttpRequest 对象来实现的。

以下是基于原生 JavaScript 的 AJAX 请求代码示例:

  1. // 创建 XMLHttpRequest 对象
  2. const xhr = new XMLHttpRequest();
  3. // 指定请求的方法和 URL
  4. xhr.open('GET', 'api_url', true); // 第三个参数 true 表示异步请求
  5. // 设置请求头(如果需要)
  6. xhr.setRequestHeader('Content-Type', 'application/json'); // 根据实际需求设置请求头
  7. // 注册一个回调函数来处理响应
  8. xhr.onreadystatechange = function() {
  9. if (xhr.readyState === 4 && xhr.status === 200) {
  10. const response = JSON.parse(xhr.responseText); // 处理响应数据
  11. // 在这里执行相应的操作
  12. console.log(response);
  13. }
  14. };
  15. // 发送请求
  16. xhr.send();

虽然 AJAX 是一种强大的技术,但相对于 Axios 和 Fetch API,它有以下一些缺点:

  • 兼容性问题:AJAX 的兼容性相对较低,尤其在旧版本的浏览器中可能会出现问题。而 Axios 和 Fetch API 使用了更现代的 JavaScript 特性,具有更好的兼容性。
  • 代码冗余:使用原生的 AJAX 需要编写较多的代码来处理不同的状态码、错误处理以及请求的拼装等。而 Axios 和 Fetch API 提供了更简洁和易用的接口,减少了代码冗余。
  • 缺乏默认配置:AJAX 不提供默认的全局配置,如请求和响应拦截器、统一的错误处理等。而 Axios 和 Fetch API 支持全局配置,并且提供了更方便的拦截器机制。
  • 功能限制:AJAX 在处理跨域请求时需要注意添加额外的处理,比如设置 CORS 头部信息或者使用 JSONP。而 Axios 和 Fetch API 提供了更直接的方式来处理跨域请求。
  • 可读性较差:由于 AJAX 使用的是回调函数来处理异步请求,可能会导致代码逻辑比较复杂,可读性较差,当我们需要发起多个AJAX请求,并在每个请求的回调函数中再进行下一次请求或其他操作时,就需要进行多层回调函数的嵌套,出现回调地狱现象。而 Axios 和 Fetch API 使用的是 Promise 或 async/await,使代码结构更加清晰易读。

Fetch


Fetch 是一种用于进行网络请求的现代 JavaScript API。它提供了一种简单、灵活且功能强大的方式,用于从服务器获取资源并处理响应。

Fetch API 在浏览器中原生支持,并且以 Promise 为基础,使得异步请求更加直观和易用。使用 Fetch API,可以执行各种类型的请求(如 GET、POST、PUT、DELETE 等),发送请求时可以设置请求头、请求参数,以及处理响应数据。

与传统的 AJAX 相比,Fetch API 具有以下优点:

  • Promise 支持:Fetch API 使用 Promise 对象来处理异步操作,使得处理异步请求的流程更加清晰、易于阅读和编写。
  • 更简洁的 API:Fetch API 提供了一个简洁的 API,使发送请求变得更加直观和简单,同时提供了丰富的配置选项(如设置请求头、请求参数等)。
  • 内置的 JSON 解析:在处理响应时,Fetch API 内置了对 JSON 数据的解析,无需手动进行解析操作。
  • 更好的错误处理:Fetch API 使用了更全面的错误处理机制,允许通过检查响应状态码来确定请求是否成功,并以不同的方式处理错误。

Fetch API 提供了一个全局的 fetch() 方法,该方法提供了一种简单、逻辑的方式来通过网络异步获取资源。

fetch() 方法的语法使用
  1. fetch(url, options)
  2. .then(response => {
  3. // 在这里处理响应
  4. })
  5. .catch(error => {
  6. // 在这里处理错误
  7. });

这里有两个参数:

url :是发送网络请求的地址。

options:发送请求参数,

  • body - http请求参数
  • mode - 指定请求模式。默认值为cros:允许跨域;same-origin:只允许同源请求;no-cros:只限于get、post和head,并且只能使用有限的几个简单标头。
  • cache - 用户指定缓存。
  • method - 请求方法,默认GET
  • signal - 用于取消 fetch
  • headers - http请求头设置
  • keepalive - 用于页面卸载时,告诉浏览器在后台保持连接,继续发送数据。
  • credentials - cookie设置,默认omit,忽略不带cookie,same-origin同源请求带cookie,inclue无论跨域还是同源都会带cookie。
  1. get 方式
  2. 只需要在url中加入传输数据,options中加入请求方式。如下面代码所示:
  3. function login(){
  4. fetch(`http://localhost:80/fetch.html?user=${user.value}&pas=${pas.value}`,{
  5. method:'GET'
  6. }).then(response=>{
  7. console.log('响应',response)
  8. })
  9. }
  10. post 方式
  11. 使用 post 发送请求时,需要设置请求头、请求数据等。
  12. fetch(`http://localhost:80/ES6练习题/53fetch.html`,{
  13. method:'POST',
  14. headers:{
  15. 'Content-Type':'application/x-www-form-urlencoded;charset=UTF-8'
  16. },
  17. body:`user=${user.value}&pas=${pas.value}`
  18. }).then(response=>{
  19. console.log('响应',response)
  20. })
  • fetch() 方法返回一个 Promise 对象,可以使用 .then() 方法来处理成功的响应,使用.catch() 方法来处理错误的情况。
  • 在 .then() 中,可以访问到 response 对象,进一步处理响应的内容。
  • 在 .catch() 中,我们可以访问到 error 对象,用于处理请求过程中的任何错误。

response

一旦获取到响应(Response),返回的对象包含以下属性:

  • response.body:一个简单的 getter,提供了响应内容的可读流(ReadableStream)。
  • response.bodyUsed:一个布尔值,用于记录响应体是否已经被使用过。
  • response.headers:与响应相关联的头部信息对象。
  • response.ok:一个布尔值,指示响应是否成功。
  • response.redirected:指示响应是否是重定向结果的布尔值。
  • response.status:响应的状态码。
  • response.statusText:与状态码对应的状态消息。
  • response.type:响应的类型。
  • response.url:响应的 URL

response 对象根据服务器返回的不同类型数据,提供了不同的读取方法。

  • 文本数据:

    • response.text():以文本形式读取响应体的数据。
    • response.json():将响应体的数据解析为JSON对象。
  • 二进制数据:

    • response.arrayBuffer():以ArrayBuffer形式读取响应体的数据。
    • response.blob():以Blob形式读取响应体的数据。
  • 表单数据:

    • response.formData():以FormData对象形式读取响应体的数据。
  • 流数据:

    • response.body:以可读流形式读取响应体的数据。
      1. body 属性返回一个 ReadableStream 对象,供用户操作,可以用来分块读取内容,
      2. 显示下载的进度就是其中一种应用。
      3. const response = await fetch('flower.jpg');
      4. const reader = response.body.getReader();
      5. //response.body.getReader() 返回一个遍历器,这个遍历器 read() 方法每次
      6. //都会返回一个对象,表示本次读取的内容块。
      7. while(true) {
      8. const {done, value} = await reader.read();
      9. if (done) {
      10. break;
      11. }
      12. console.log(`Received ${value.length} bytes`)
      13. }
  • 这些方法返回一个 Promise,当解析完成时,Promise 将被解析为相应的数据类型。

如果是上传数据:

  1. 将上个实例,改写成 post 方式提交数据,代码如下:
  2. fetch(`http://localhost:80/ES6练习题/53fetch.html`,{
  3. method:'POST',
  4. headers:{
  5. 'Content-Type':'application/x-www-form-urlencoded;charset=UTF-8'
  6. },
  7. body:`user=${user.value}&pas=${pas.value}`
  8. }).then(response=>{
  9. console.log('响应',response)
  10. })
  11. //如果是提交json数据时,需要把json转换成字符串。如
  12. body:JSON.stringify(json)
  13. //如果提交的是表单数据,使用 formData转化下,如:
  14. body:new FormData(form)
  15. //上传文件,可以包含在整个表单里一起提交,如:
  16. const input = document.querySelector('input[type="file"]');
  17. const data = new FormData();
  18. data.append('file', input.files[0]);
  19. data.append('user', 'foo');
  20. fetch('/avatars', {
  21. method: 'POST',
  22. body: data
  23. });
  24. //上传二进制数据,将 bolb 或 arrayBuffer 数据放到body属性里,如:
  25. let blob = await new Promise(resolve =>
  26. canvasElem.toBlob(resolve, 'image/png')
  27. );
  28. let response = await fetch('/article/fetch/post/image', {
  29. method: 'POST',
  30. body: blob
  31. });

response.clone()

stream 对象只能读取一次,读取完就没了,这意味着,上边的五种读取方法,只能使用一个,否则会报错。

因此 response 对象提供了 clone() 方法,创建 respons 对象副本,实现多次读取。

  1. const response1 = await fetch('flowers.jpg');
  2. const response2 = response1.clone();
  3. const myBlob1 = await response1.blob();
  4. const myBlob2 = await response2.blob();
  5. image1.src = URL.createObjectURL(myBlob1);
  6. image2.src = URL.createObjectURL(myBlob2);​​​​​​​
fetch 常见坑

fetch 是相对较新的技术,IE浏览器不支持,还有其他低版本浏览器也不支持,因此如果使用fetch时,需要考虑浏览器兼容问题。

解决办法:引入 polyfill 完美支持 IE8 以上。

  • 由于 IE8 是 ES3,需要引入 ES5 的 polyfill: es5-shim, es5-sham
  • 引入 Promise 的 polyfill:es6-promise
  • 引入 fetch 探测库:fetch-detector
  • 引入 fetch 的 polyfill: fetch-ie8
  • 可选:如果你还使用了 jsonp,引入 fetch-jsonp
  • 可选:开启 Babel 的 runtime 模式,现在就使用 async/await

polyfill 的原理就是探测fetch是否支持,如果不支持则用 xhr 实现。支持 fetch 的浏览器,响应中文会乱码,所以使用 fetch-detector 和 fetch-ie8 解决乱码问题。

fetch默认不带cookie

传递cookie时,必须在header参数内加上 credentials:'include',才会像 xhr 将当前cookie 带有请求中。

异常处理

fetch 不同于 xhr ,xhr 自带取消、错误等方法,所以服务器返回 4xx 或 5xx 时,是不会抛出错误的,需要手动处理,通过 response 中的 status 字段来判断。

取消请求

在标准的 Fetch API 中,没有提供直接取消 Fetch 请求的内置方法。但是,可以使用以下方法来模拟或实现取消 Fetch 请求的效果。

使用 AbortController 和 AbortSignal:这是一种较新的浏览器特性,用于生成可以取消请求的信号。可以创建一个 AbortController对象,然后将其关联到 Fetch 请求中,当需要取消请求时,调用 AbortController 的 abort()方法:

  1. // 创建 AbortController 和关联的 signal
  2. const abortController = new AbortController();
  3. const signal = abortController.signal;
  4. // 发起 Fetch 请求,并将 signal 传递给 fetch 函数
  5. fetch(url, { signal })
  6.   .then(response => {
  7.     // 处理响应
  8.   })
  9.   .catch(error => {
  10.     if (error.name === 'AbortError') {
  11.       // 请求已被取消
  12.     } else {
  13.       // 处理其他错误
  14.     }
  15.   });
  16. // 当需要取消请求时,调用 abort() 方法
  17. abortController.abort();

Axios


Axios 是一个基于 Promise 网络请求第三方库,用于在浏览器和 Node.js 中进行 HTTP 请求。在服务端它使用原生 node.js http 模块, 而在客户端,本质上还是对原生XMLHttpRequest的封装,只不过它是基于Promise的,符合最新的ES规范

具备以下特点:

  • 在浏览器中创建XMLHttpRequest请求
  • 在node.js中发送http请求
  • 支持Promise API
  • 拦截请求和响应
  • 转换请求和响应数据
  • 取消要求
  • 自动转换JSON数据
  • 客户端支持防止CSRF/XSRF(跨域请求伪造)
使用

// 使用 npm 安装
npm install axios
// 使用 yarn 安装
yarn add axios

请求方法

axios 支持通过简写方式来执行不同类型的请求:

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]])
对于这些方法,第一个参数是请求的 URL,config 和 data 分别是请求的配置项和请求参数,这两个参数都是可选的。

  1. 下面来进行一个简单的 get 请求:
  2. axios.get('https://api.example.com/data')
  3. .then(response => {
  4. // 处理成功响应
  5. console.log(response.data);
  6. })
  7. .catch(error => {
  8. // 处理错误
  9. console.error(error);
  10. });
  11. //post
  12. const options = {
  13. headers: {'X-Custom-Header': 'value'}
  14. };
  15. axios.post('/save', { a: 10 }, options)
  16. .then(response => {
  17. // 处理成功响应
  18. console.log(response.data);
  19. })
  20. .catch(error => {
  21. // 处理错误
  22. console.error(error);
  23. });

当作为第二个参数传递给 axios.post 函数时,Axios 会自动将 JavaScript 对象序列化为 JSON。这样就无需将 POST 正文序列化为 JSON。Axios 还会自动将 Content-Type 请求头设置为 application/json

特点

axios实例的相关配置
(1)配置列表

  • baseURL:请求的域名(基本地址)。
  • timeout:请求的超时时长,超出后后端返回401。
  • 备注:一般由后端定义,后端的接口需要的处理时长较长的时候,如果请求的时间过长,后端处理不过来,就会阻塞,给服务器造成较大的压力。设置后,可以及时释放掉。
  • url:请求路径。
  • method:请求方法。如:get、post、put、patch、delete等。
  • headers:请求头。
  • params:将请求参数拼接到url上
  • data:将请求参数放置到请求体里
  • withCredentials:置是否发送跨域请求时包含凭证信息(如 Cookie)。

请求拦截、响应拦截

Axios 中,可以使用拦截器来拦截请求和响应,并在其被发送或接收之前进行一些额外的处理,可以通过 axios.interceptors 对象来添加拦截器。

  1. // 添加请求拦截器
  2. axios.interceptors.request.use(config => {
  3. // 在发送请求之前做一些处理
  4. console.log('请求拦截器');
  5. // 修改请求配置
  6. config.headers['Authorization'] = 'Bearer token';
  7. return config;
  8. }, error => {
  9. // 处理请求错误
  10. console.error('请求出错:', error);
  11. });
  12. // 添加响应拦截器
  13. axios.interceptors.response.use(response => {
  14. // 在接收到响应数据之前做一些处理
  15. console.log('响应拦截器');
  16. // 修改响应数据
  17. response.data = { ...response.data, extraField: 'Extra Value' };
  18. return response;
  19. }, error => {
  20. // 处理响应错误
  21. console.error('响应出错:', error);
  22. });
  23. // 发送请求
  24. axios.get('https://api.example.com/data')
  25. .then(response => {
  26. // 处理成功响应
  27. console.log(response.data);
  28. })
  29. .catch(error => {
  30. // 处理请求或响应错误
  31. console.error(error);
  32. });

单个请求响应拦截

可以使用 transformRequest 方法在请求发送之前对请求数据进行转换和处理,它是一个请求拦截器,是一个可选的函数。

transformRequest 函数接收两个参数:requestData 和 requestHeaders

requestData 是要发送的请求数据,requestHeaders 是要发送的请求头信息。

可以在transformRequest 函数内部对这些参数进行修改,并将修改后的值返回。返回的结果将作为实际发送请求的数据。
 

  1. axios({
  2. url: 'https://api.example.com/data',
  3. method: 'post',
  4. data: {
  5. id: 12345,
  6. name: 'John Doe'
  7. },
  8. transformRequest: (data, headers) => {
  9. // 对请求数据进行转换和处理
  10. const modifiedData = { ...data }; // 复制原始数据
  11. // 修改数据或添加额外字段
  12. modifiedData.extraField = 'Extra Value';
  13. // 修改请求头信息
  14. headers['Content-Type'] = 'application/json';
  15. return JSON.stringify(modifiedData); // 返回处理后的数据
  16. }
  17. })
  18. .then(response => {
  19. // 处理成功响应
  20. console.log(response.data);
  21. })
  22. .catch(error => {
  23. // 处理错误
  24. console.error(error);
  25. });
  26. axios.get('https://api.example.com/data', {
  27. transformResponse: (data) => {
  28. // 对响应数据进行转换和处理
  29. const parsedData = JSON.parse(data); // 解析 JSON 字符串
  30. // 修改数据或添加额外字段
  31. parsedData.extraField = 'Extra Value';
  32. return parsedData; // 返回处理后的数据
  33. }
  34. })
  35. .then(response => {
  36. // 处理成功响应
  37. console.log(response.data);
  38. })
  39. .catch(error => {
  40. // 处理错误
  41. console.error(error);
  42. });

客户端支持 XSRF 防护

跨站请求伪造(简称 XSRF)是一种攻击 Web 应用的方法,其中攻击者将自己伪装成合法且受信任的用户,以影响应用程序与用户浏览器之间的交互。有很多方法可以执行此类攻击,包括XMLHttpRequest。

幸运的是,Axios 通过允许在发出请求时嵌入额外的身份验证数据来防止 XSRF。这使得服务器能够发现来自未经授权的位置的请求。以下是使用 Axios 完成此操作的方法:
 

  1. const options = {
  2. method: 'post',
  3. url: '/login',
  4. xsrfCookieName: 'XSRF-TOKEN',
  5. xsrfHeaderName: 'X-XSRF-TOKEN',
  6. };
  7. axios(options)
  8. .then(response => {
  9. // 处理成功响应
  10. console.log(response.data);
  11. })
  12. .catch(error => {
  13. // 处理请求错误
  14. console.error(error);
  15. });

这里有两个 xsrf 相关的属性:

  • xsrfCookieName: 'XSRF-TOKEN':用于跨站请求伪造(XSRF/CSRF)保护的配置选项之一。它指定了存储 XSRF 令牌的 cookie 的名称。XSRF 令牌用于防止恶意网站发起对已验证用户的请求。
  • xsrfHeaderName: 'X-XSRF-TOKEN':用于跨站请求伪造(XSRF/CSRF)保护的配置选项之一。它指定了包含 XSRF 令牌的请求头的名称。服务器端可以通过检查该请求头来验证请求的合法性。

请求进度

Axios 的另一个有趣的功能是能够监控请求的进度,这在下载或上传大文件时特别有用,可以使用onUploadProgress 和 onDownloadProgress 两个配置选项来实现。

对于上传进度,可以使用 onUploadProgress 配置选项。它会在上传数据时触发,并提供关于上传进度的信息。
 

  1. axios.post('/upload', data, {
  2. onUploadProgress: progressEvent => {
  3. const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
  4. console.log(`上传进度:${percentCompleted}%`);
  5. },
  6. })
  7. .then(response => {
  8. console.log(response.data);
  9. })
  10. .catch(error => {
  11. console.error(error);
  12. });

这里发送了一个 POST 请求,在配置选项中使用了 onUploadProgress。当数据上传过程中触发进度事件时,回调函数会被执行。在回调函数中,我们计算出了已上传数据的百分比,并将其打印出来。

对于下载进度,可以使用 onDownloadProgress 配置选项。它会在接收到响应数据时触发,并提供关于下载进度的信息。

  1. axios.get('/download', {
  2. onDownloadProgress: progressEvent => {
  3. const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
  4. console.log(`下载进度:${percentCompleted}%`);
  5. },
  6. })
  7. .then(response => {
  8. console.log(response.data);
  9. })
  10. .catch(error => {
  11. console.error(error);
  12. });

取消请求(不常用)

在 Axios 中,可以使用取消令牌(cancel token)来取消请求。取消令牌是一个对象,它表示一个具体的取消操作,并允许在需要时中止请求。

  1. let source = axios.CancelToken.source();
  2. axios
  3. .get("/data.json", {
  4. cancelToken: source.token
  5. })
  6. .then(res => {
  7. console.log(res);
  8. }).catch(err=>{
  9. if (axios.isCancel(error)) {
  10. console.log('请求已被取消:', error.message);
  11. } else {
  12. console.error(error);
  13. } })
  14. // 取消请求(参数msg)
  15. source.cancel('自定的的字符串可选')

这里,先创建了一个取消令牌源 source。然后,发送 GET 请求时将 cancelToken 配置选项设置为 source.token,即将取消令牌与该请求关联起来。当需要取消请求时,调用source.cancel() 方法,并传入取消请求的原因作为参数。

在请求的 .catch() 方法中,我们使用 axios.isCancel(error) 来判断捕获的错误是否是一个已取消的请求。如果是取消请求导致的错误,则会打印出 ‘请求已被取消’ 的提示信息。否则,将打印出其他类型的错误。

注意,如果不设置 timeout 选项,默认情况下 Axios 请求是没有超时限制的。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/148359
推荐阅读
相关标签
  

闽ICP备14008679号