ajax和fetch、axios的区别以及axios原理

从原生的XHR到jquery ajax,再到现在的axios和fetch,究竟发生了哪些变化,我们接下来就来探讨一下。

jquery ajax

它是对原生XHR的封装,随着vue、react框架的兴起,很多情况下我们只需使用ajax可是却要引入整个jquery,这是非常不合理。

$.ajax({
 type:'POST',
 url:url,
 data:data,
 dataType:dataType,
 success:function(){},
 error:funciton(){}
})

优点:响应快,使用方便。
缺点:

  • 针对MVC的编程设计,不符合现在的MVVM趋势
  • 基于原生的XHR开发。
  • JQuery较大,单纯的使用ajax要引入这个文件不合理。

fetch

fetch解决了使用ajax引入这个jquery文件的问题。fetch号称是ajax的替代品,它的API是基于Promise设计的。

//原生的XHR
var xhr=new XHRHttprequest();
xhr.open('GET',url);
xhr.onreadystatechange=funciton(){
 if(xhr.readyState===4&&xhr.status===200){
    console.log(xhr.responseText);
}
}
xhr.send()
//fetch
try {
  let response = await fetch(url);//await后面是个promise对象
  let data = await response.json();
  console.log(data);
} catch(e) {
  console.log("error:", e);
}

优势:

  • 更加底层,提供的API丰富。
  • 脱离了XHR。
  • 跨域处理(mode为‘no-cors’)
  • 基于promise实现,支持async/await
fetch('/testPost', {
    method: 'post',
    mode: 'no-cors',
    data: {}
}).then(function() {});

缺点:

  • fetch只有对网络请求报错,对400,500都当作成功的请求,并不会reject。
  • fetch默认不会带cookie,需要添加配置项:fetch(url,{credentials:'include'})
  • 所以 版本的IE均不支持原生Fetch。
  • fetch不支持abort,不支持超时控制,使用setTimeout及Promise.reject的实现的超时控制并不能阻止请求过程继续在后台运行,造成了流量的浪费

Axios

Vue2.0之后,Axios受到了更多人的关注。Axios本质是对原生XHR封装,需要一个promise对返回的结果进行处理。

  • 支持Promise API
  • 将返回的数据自动转化成JSON数据====transformResponse
  • 可以取消请求====request.abort()
  • 提供一些并发请求的接口。
function getUserAccount() {
  return axios.get('/user/12345');
}

function getUserPermissions() {
  return axios.get('/user/12345/permissions');
}

axios.all([getUserAccount(), getUserPermissions()])
  .then(axios.spread(function (acct, perms) {
    // Both requests are now complete
  }));
  • 防止CSRF攻击:每次请求都要带一个从cookie中获取的key值,根据同源策略,假冒的网站拿不到cookie中的key,后台可以根据这个请求判断是不是有人假冒,从而采取正确的策略。
axios({
  methods:'post',
  url:url,
  data:data

}).then((resopnse)=>{
  console.log(response)
}).catch((error)=>{
   console.log(error)
})

Axios的原理解读

底层还是对XHR的封装,只不过需要一个Promise对象对返回的结果进行处理。axios在浏览器端是和Ajax底层的原理一样,都是通过XMLHttpRequest对象进行的一次封装。
NPM包流程:

  • index.js入口文件:导出一个axios.js文件
  • axios.js文件:导出了axois module.exports=axios;axios又是什么?axios是向createInstance传了一个defaultConfig参数的返回值。
//Axios/lib/axios.js
function createInstance(defaultConfig) {
  var context = new Axios(defaultConfig);
  ...
  return instance;
}

var axios = createInstance(defaults);
  • defaults.js文件:参数是什么?参数是一些header信息等一些默认值。
    知识点:axios可以同时支持客户端和服务端的请求。原理就是通过浏览器XHR和proess来区分请求。
/ 通过nodejs中的process和浏览器的XMLHttpRequest来区别当前在前端还是nodejs中
function getDefaultAdapter() {
  var adapter;
  if (typeof process !== 'undefined' && Object.prototype.toString.call(process) === '[object process]') {
    adapter = require('./adapters/http');//Nodejs端的Axios的实现:基于http或者https模块来发起请求的
  } else if (typeof XMLHttpRequest !== 'undefined') {
    adapter = require('./adapters/xhr');//浏览器中axios的实现:对ajax库的封装,只不过暴露一个Promise出去
  }
  return adapter;
}

var defaults = {
  adapter: getDefaultAdapter(),
  ... 
  timeout: 0,

  xsrfCookieName: 'XSRF-TOKEN',
  xsrfHeaderName: 'X-XSRF-TOKEN',

  maxContentLength: -1,
 
  validateStatus: function validateStatus(status) {
    return status >= 200 && status < 300;
  }
};

defaults.headers = {
  common: {
    'Accept': 'application/json, text/plain, */*'
  }
};
  • /lib/core/Axios.js:看看createInstance内部是什么?就是将传入的参数,挂载到自己的this上,新增了一个拦截器对象interceptors,这个对象里有request和response属性。这个属性中的InterceptorManager这个构造函数又是干嘛的?
  • /lib/IntercetporManager.js:拦截器中的构造函数有三个方法。use、eject、forEach。
/ 进入core/InterceptorManager.js
InterceptorManager.prototype.use = function() {...}//使用拦截器
InterceptorManager.prototype.eject =  function() {...}//删除use过的内容
InterceptorManager.prototype.forEach = function forEach(fn) {...}//循环执行fn

目前为止是createInstance函数执行返回的值就是axios的一些过程,给大家一个详细的连接,博主写的很好,我只是做些笔记。axios详细解读

你可能感兴趣的:(axios,fetch,axios)