网络请求 xhr、ajax、axios与fetch的区别比

618 阅读2分钟

一、XMLHttpRequest 对象

  • XMLHttpRequest 对象是最开始用于向服务器请求数据的技术

  • 其实在实际开发中使用的各种第三方请求服务器的插件框架都是封装了的 XMLHttpRequest 对象

基本使用

let xhr = new XMLHttpRequest();
xhr.open('GET', '/url', true);
xhr.send();

完整的XMLHttpRequest 对象封装

let xhr = new XMLHttpRequest();
// 请求成功回调函数
xhr.onload = e => {
    console.log('request success');
};
// 请求结束
xhr.onloadend = e => {
    console.log('request loadend');
};
// 请求出错
xhr.onerror = e => {
    console.log('request error');
};
// 请求超时
xhr.ontimeout = e => {
    console.log('request timeout');
};
// 请求回调函数.XMLHttpRequest标准又分为Level 1和Level 2,这是Level 1和的回调处理方式
// xhr.onreadystatechange = () => {
//    if (xhr.readyState !== 4) {
//      return;
//    }
//    const status = xhr.status;
//    if ((status >= 200 && status < 300) || status === 304) {
//      console.log('request success');
//    } else {
//      console.log('request error');
//    }
//  };

xhr.timeout = 0; // 设置超时时间,0表示永不超时
// 初始化请求
xhr.open('GET/POST/DELETE/...', '/url', true || false);
// 设置期望的返回数据类型 'json' 'text' 'document' ...
xhr.responseType = '';
// 设置请求头
xhr.setRequestHeader('', '');
// 发送请求
xhr.send(null || new FormData || 'a=1&b=2' || 'json字符串');

二、ajax

  • ajax 对原生的 XMLHttpRequest 对象的封装,做了兼容处理,简化了使用,同时增加了对 JSONP 的支持,可以简单处理部分跨域

  • ajax 的缺点非常多

  1. 如果有多个请求,并且有依赖关系的话,容易形成回调地狱
  2. 本身是针对 MVC 的编程,不符合现在前端 MVVM 的浪潮
  3. ajax是jQuery中的一个方法。如果只是要使用ajax却要引入整个jQuery非常的不合理
$.ajax({
    type: 'POST',  // GET 或 POST
   url: url,    // 发送请求的 URL
   data: data,  // 要发送到服务器的数据
   dataType: dataType, // 预期的服务器响应的数据类型
   success: function () {}, // 请求成功时运行的函数
   error: function () {}   // 请求失败要运行的函数
});

扩展:简单说下 MVVM

  • MVVM (Model-View-ViewModel) 源自于经典的 Model-View-Controller (MVC)模式

  • MVVM 的出现促进了GUI前端开发与后端业务逻辑的分离,极大地提高了前端开发效率

  • MVVM 的核心是 ViewModel 层,它就像一个中转站(value converter),负责转换 Model 中的数据对象来让数据变得更容易管理和使用,该层向上与视图层进行双向数据绑定,向下与 Model 层通过接口请求进行数据交互,起呈上启下作用。View 层展现的不是 Model 层的数据,而是 ViewModel 的数据,由 ViewModel 负责与 Model 层交互,这就完全解耦了 View 层和 Model 层,这个解耦是至关重要的,它是前后端分离方案实施的最重要一环

image.png

三、axios

  • Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。本质也是对原生XMLHttpRequest 对象的封装,只不过它是 Promise 的实现版本,符合最新的ES规范

  • axios 的优点有很多,Vue2.0之后,尤雨溪一直推荐大家使用 axios 来请求数据

  1. 从浏览器中创建 XMLHttpRequests 对象
  2. 从 node.js 创建 http 请求
  3. 支持 Promise API
  4. 支持请求拦截和响应拦截
  5. 转换请求数据和响应数据
  6. 可以取消请求
  7. 自动转换 JSON 数据
  8. 客户端支持防御 XSRF
  • 缺点就是只支持现代浏览器
axios({
    method: 'post',
    url: '/user/12345',
    data: {
      firstName: 'liu',
      lastName: 'weiqin'
    }
  })
  .then(res => console.log(res))
  .catch(err => console.log(err))

四、fetch

  • fetch 号称是 AJAX 的替代品,是在 ES6 出现的,使用了 ES6 中的 promise 对象。Fetch 是基于 promise 设计的。 Fetch 的代码结构比起 ajax 简单多了, 参数有点像 JQuery ajax。 但是,一定要记住:fetch 不是 ajax的进一步封装,而是原生 JS , 没有使用 XMLHttpRequest 对象

  • fetch 可以处理跨域,只需要在配置中,添加mode:'no-cors'就可以跨域了

fetch('/users.json', {
    method: 'post', 
    mode: 'no-cors',
    data: {}
}).then(function() { /* handle response */ });
  • fetch 是一个低层次的 API,可以代替原生的XHR,但是需要进行二次封装,比如 例如:
  1. 当接收到一个代表错误的 HTTP 状态码时,从 fetch() 返回的 Promise 不会被标记为 reject,即使响应的 HTTP 状态码是 404 或 500。只有网络错误这些导致请求不能完成时, fetch 才会被 reject。所以需要封装去处理

  2. fetch 默认不会带 cookie,需要添加配置项: fetch(url, {credentials: 'include'})

  3. fetch 不支持 abort ,不支持超时控制,使用 setTimeout 及 Promise.reject 来实现超时控制并不能阻止请求过程继续在后台运行,造成了流量的浪费

  4. fetch 没有办法原生监测请求的进度,而 XHR 可以

  5. fetch 对浏览器兼容性并不太好,IE 不支持

// 通过fetch获取百度的错误提示页面
fetch('https://www.baidu.com/rec?platform=wise&ms=1&rset=rcmd&word=123&qid=11327900426705455986&rq=123&from=844b&baiduid=A1D0B88941B30028C375C79CE5AC2E5E%3AFG%3D1&tn=&clientWidth=375&t=1506826017369&r=8255', { // 在URL中写上传递的参数
    method: 'GET',
    headers: new Headers({
      'Accept': 'application/json' // 通过头指定,获取的数据类型是JSON
    })
  })
  .then((res)=>{
    return res.json() // 返回一个Promise,可以解析成JSON
  })
  .then((res)=>{
    console.log(res) // 获取JSON数据
  })