一文掌握ajax、fetch和axios的区别对比

目录
  • AJAX、Fetch、axios
    • AJAX
    • 创建AJAX
    • AJAX的缺点:
    • axios原理
    • axios的特点
    • axios常用的方法
    • put和patch的区别
    • axios相关配置
    • axios拦截器执行顺序问题
    • 为什么axios中需要拦截器
    • 为什么请求拦截2会在请求拦截1之前执行呢?
  • Fetch、ajax与axios的区别
  • Fetch和Ajax比有什么优点
  • 总结
    • axios源码分析
    • axios的执行流程

AJAX、Fetch、axios

AJAX

AJAX可以在不更新全局的情况下更新局部页面。通过在与服务器进行数据交换,可以使网页实现异步更新。

AJAX的原理就是通过XHR对象来向服务器发起异步请求,从服务器获得数据,然后用JS来操作DOM更新页面。领导想找小李汇报一下工作,就委托秘书去叫小李,自己就接着做其他事情,直到秘书告诉他小李已经到了,最后小李跟领导汇报工作。Ajax请求数据流程与“领导想找小李汇报一下工作”类似,上述秘书就相当于XMLHttpRequest对象,领导相当于浏览器,响应数据相当于小李。浏览器可以发送HTTP请求后,接着做其他事情,等收到XHR返回来的数据再进行操作。

创建AJAX

// 1. 创建 XMLHttpRequest 实例
let xhr = XMLHttpRequest()
// 2. 打开和服务器的连接
xhr.open('get', 'URL')
// 3.发送
xhr.send()
// 4. 接收变化。
xhr.onreadystatechange = () => {
    if(xhr.readyState == 4 && xhr.status == 200){   // readyState: ajax 状态,status:http 请求状态
        console.log(xhr.responseText);   //响应主体
    }
}
  • 创建AJAX实例:let xhr = new XMLHttpRequest()
  • 打开请求,配置请求前的配置项:xhr.open([http method], [url], [async], [userName], [userPass])
  1. http methods 请求方式:post,get,delete,put,head,options,trace,connect
  2. url:想服务器请求的路径
  3. async:是否为异步请求
  4. userName、userPass:用户名与密码
  • 通过XMLHttpRequest.open()方法与服务器建立连接
  • 发送请求:XMLHttpRequest.send() 方法中如果 Ajax 请求是异步的则这个方法发送请求后就会返回,如果Ajax请求是同步的,那么请求必须知道响应后才会返回。
  • 通过XMLHttpRequest对象的onreadystatechange事件监听服务器端的通信状态
  • 接收数据并进行处理
  • 将处理后的结果更新到页面上

AJAX的缺点:

  • 本是针对MVC架构,不符合前端MVVM的浪潮
  • 基于原生的XHR开发
  • 配置和调用方式混乱

axios原理

axios是使用promise封装的ajax,它内部有两个拦截器,分别是request拦截器和response拦截器。

  • 请求拦截器的作用是在请求发送之前进行一些操作,例如在每个请求体上加入token
  • 响应拦截器的作用是接收到响应后做的一些操作,例如登录失效后需要重新登录跳转到登录页

axios的特点

  • 由浏览器端发起请求,在浏览器中创建XHR
  • 支持promise API
  • 监听请求和返回
  • 更好的格式化,自动将数据转换为json数据
  • 安全性更高,可抵御CSRF攻击

axios常用的方法

axios常用的方法有getpostputpatchdelete等。其中getpost返回的都是promise对象,可以使用promise方法

axios.get(url[, config]):get请求用于列表和信息查询

axios.get('apiURL', {
    param: {
        id: 1
    }
    // param 中的的键值对最终会 ? 的形式,拼接到请求的链接上,发送到服务器。
}).then(res => {
    console.log(res);
})
.catch( error => {
    console.log(error)
}

axios.delete(url[, config]):删除

axios.delete('apiURL', {
    params: {
        id: 1
    },
    timeout: 1000
})

axios.post(url[, data[, config]]):post请求用于信息的添加

axios.post('apiURL',{
        user: '小新',
        age: 18
}).then( res => {
    console.log(res);
})
.catch( error => {
    console.log(error)
}

axios.put(url[, data[, config]]):更新操作

axios.put('apiURL', {
    name: '小新',
})

axios.patch(url[, data[, config]]):更新操作

axios.patch('apiURL', {
    id: 13,
},{
   timeout: 1000,
})

put和patch的区别

patch方法用来更新局部资源,假设我们有一个UserInfo,里面有userId,userName,userGender等10个字段。可你的编辑功能因为需求,在某个特别的页面里只能修改userName,这个时候就可以使用patch

put也适用于更新数据,但必须提供完整的资源对象。

axios相关配置

  • url:用于请求服务器的url
  • method:请求方法,默认为get
  • baseURL:会自动加到url前面
  • proxy:用于配置代理
  • transformRequest:允许在服务器发送请求之前修改请求数据

axios拦截器执行顺序问题

  • 请求拦截:axios的请求拦截器会先执行最后指定的回调函数,再依次向前执行
  • 响应拦截:axios的响应拦截器会先执行最先执行的回调函数,再依次向前执行

例如:

axios.interceptors.request.use(config => {
  console.log(`请求拦截1`);
  return config;
});
axios.interceptors.request.use(config => {
  // 在发送请求之前做些什么
  console.log(`请求拦截2`);
  return config;
});

// 添加响应拦截器
axios.interceptors.response.use(response => {
  // 对响应数据做点什么
  console.log(`成功的响应拦截1`);
  return response.data;
});

// 添加响应拦截器
axios.interceptors.response.use(response => {
  // 对响应数据做点什么
  console.log(`成功的响应拦截2`);
  return response;
});

// 发送请求
axios.get('/posts')
  .then(response => {
    console.log('成功了');
  })

执行结果为

console.log("请求拦截2");
console.log("请求拦截1");
console.log("成功的响应拦截1");
console.log("成功的响应拦截2");
console.log("成功了");

为什么axios中需要拦截器

在SPA应用中,通常会使用token进行用户身份认证,这就要求每次请求必须携带用户的身份信息,针对这个需求,为了避免在每个请求中单独处理,我们可以通过封装统一的request函数来为每隔请求统一添加token信息。

但如果想为某些请求添加缓存时间或者控制某些请求的调用频率的话,我们就需要不断地修改request函数来扩展对应的功能。此时,如果在考虑对响应进行统一处理,我们的request函数将变得越来越庞大,也越来越难维护。所以axios为我们提供了拦截器。

为什么请求拦截2会在请求拦截1之前执行呢?

axios源码中将发送请求分为了请求拦截器、发送请求、响应拦截器、相应回调,通过Promise的链式调用将这些部分结合起来了,这样就得到了发送请求拿到数据的全部过程。

下面分析源码:

  • 代码开始构建了一个config配置对象,用于第一次执行Promise返回一个成功的Promise
  • 最核心的数组chain,这个数组中保存了请求拦截器、响应拦截器和发送请求函数。该数组中间放的是发送请求的函数,左边放的是请求拦截器,右边放的是响应拦截器。在第一步中返回的Promise对象,将遍历chain数组逐一执行里面的函数,并返回新的Promise对象
  • 往数组中添加请求拦截函数,依照axios请求的执行顺序,请求拦截器应该在发送请求之前执行,故应该添加在发送请求函数的前面,使用unshift方法
  • 往数组中添加响应拦截器函数,依照axios请求的执行顺序,响应拦截器应该在发送请求之后执行,故应该添加在发送请求函数的后面,所以使用的是数组的push方法
  • Promise遍历执行,每次从chain中取出两个 函数执行(一个成功回调,一个失败回调)
  • 最后返回一个Promise对象,用于执行响应数据的回调

fetch
fetch是http请求数据的方式,它使用Promise,但不使用回调函数。fetch采用模块化设计,通过数据流处理数据,对于请求大文件或网速慢的情况相当有用。默认情况下fetch不会接收或发送cookies。

优点:

  • 采用模块化思想,将输入、输出、状态跟踪分离
  • 基于promise,返回一个promise对象

缺点:

  • 过于底层,有很多状态码没有进行封装
  • 无法阻断请求
  • 兼容性差无法检测请求进度

Fetch、ajax与axios的区别

  • 传统的ajax利用的是HMLHttpRequest这个对象,和后端进行交互。
  • JQury ajax是对原生XHR的封装,多请求间有嵌套的话就会出现回调地狱的问题。
  • axios使用promise封装XHR,解决了回调地狱的问题。而Fetch没有使用XHR,使用的是promise

Fetch和Ajax比有什么优点

Fetch使用的是promise,方便使用异步,没有回调地狱的问题。

总结

Ajax是一种web数据交互的方式,它可以使页面在不重新加载的情况下请求数据并进行局部更新,它内部使用了XHR来进行异步请求。Ajax在使用XHR发起异步请求时得到的是XML格式的数据,如果想要JSON格式,需要进行额外的转换;Ajax本身针对的是MVC框架,不符合现在的MVVM架构Ajax有回调地狱问题;Ajax的配置复杂

Fetch是XHR的代替品,它基于Promise实现的,并且不使用回调函数,它采用模块化结构设计,并使用数据流进行传输,对于大文件和网速慢的情况非常友好。但是Fetch不会对请求和响应进行监听;不能阻断请求;过于底层,对一些状态码没有封装;兼容性差。

axios是基于PromiseXHR进行封装,它内部封装了两个拦截器,分别是请求拦截器和响应拦截器。请求拦截器用于在请求发出之前进行一些操作,比如:设置请求体,携带Cookie、token等;响应拦截器用于在得到响应后进行一些操作,比如:登录失效后跳转到登录页面重新登录。axios有get、post、put、patch、delete等方法。axios可以对请求和响应进行监听;返回Promise对象,可以使用Promise的API;返回JSON格式的数据;由浏览器发起请求;安全性更高,可以抵御CSRF攻击。

axios源码分析

axios的执行流程

  • 使用axios.create创建单独的实例,或直接使用axios实例
  • 对于axios调用进入到request()中进行处理
  • 执行请求拦截器
  • 请求数据转换器,将传入的数据进行处理,比如JSON.stringify(data)
  • 执行适配器,判断是浏览器端还是node端,以执行不同的方法
  • 响应数据转换器,对服务器端的数据进行处理,比如JSON.parse(data)
  • 执行响应拦截器,对服务器端数据进行处理,比如token失效跳转到登录页
  • 返回数据

入口文件(lib/axios.js)

导出的axios就是 实例化后的对象,还在其上挂载create方法,以供创建独立的实例,实现实例之间互不影响。

// 创建实例过程的方法
function createInstance(defaultConfig) {
  return instance;
}
// 实例化
var axios = createInstance(defaults);

// 创建独立的实例,隔离作用域
axios.create = function create(instanceConfig) {
  return createInstance(mergeConfig(axios.defaults, instanceConfig));
};
// 导出实例
module.exports = axios;

createInstance()

function createInstance(defaultConfig) {
  // 实例化,创建一个上下文
  var context = new Axios(defaultConfig);

  // 平时调用的 get/post 等等请求,底层都是调用 request 方法
  // 将 request 方法的 this 指向 context(上下文),形成新的实例
  var instance = bind(Axios.prototype.request, context);

  // Axios.prototype 上的方法 (get/post...)挂载到新的实例 instance 上,
  // 并且将原型方法中 this 指向 context
  utils.extend(instance, Axios.prototype, context);

  // Axios 属性值挂载到新的实例 instance 上
  // 开发中才能使用 axios.default/interceptors
  utils.extend(instance, context);

  return instance;
}

createInstance执行流程:

  • 通过构造函数Axios创建实例context,作为下面request方法的上下文(this指向)
  • Axios.prototype.request方法作为实例使用,并把this指向context,形成新的实例instance
  • 将构造函数Axios.prototype上的方法挂载到新的实例instance上,然后将原型各个方法中的this指向context,这样才能使用get、post等方法
  • Axios的属性挂载到instance

可以看到axios不是简单的创建实例context,而是在context上进行this绑定形成新的实例,然后将Axios属性和请求方法挂载到新的实例上

拦截器(lib/core/InterceptorManager.js)

拦截器涉及一个属性和三个方法:

  • handler:存放use注册的回调函数
  • use:注册成功和失败的回调函数
  • eject:删除注册过的函数
  • forEach:遍历回调函数
function InterceptorManager() {
  // 存放 use 注册的回调函数
  this.handlers = [];
}

InterceptorManager.prototype.use = function use(fulfilled, rejected, options) {
  // 注册成功和失败的回调函数
  this.handlers.push({
    fulfilled: fulfilled,
    rejected: rejected,
    ...
  });
  return this.handlers.length - 1;
};

InterceptorManager.prototype.eject = function eject(id) {
  // 删除注册过的函数
  if (this.handlers[id]) {
    this.handlers[id] = null;
  }
};

InterceptorManager.prototype.forEach = function forEach(fn) {
  // 遍历回调函数,一般内部使用多
  utils.forEach(this.handlers, function forEachHandler(h) {
    if (h !== null) {
      fn(h);
    }
  });
};

dispatchRequest(lib/core/dispatchRequest.js)

dispatchRequest主要做了以下操作:

  • transformRequest: 对 config 中的 data 进行加工,比如对 post 请求的 data 进行字符串化(JSON.stringify(data))
  • adapter:适配器,包含浏览器端 xhr 和 node 端的 http
  • transformResponse: 对服务端响应的数据进行加工,比如 JSON.parse(data)

取消请求(lib/cancel/CancelToken.js)

var CancelToken = axios.CancelToken;
var source = CancelToken.source();
axios.get('/user/12345', {
  cancelToken: source.token
}).catch(function(thrown) {
  if (axios.isCancel(thrown)) {
    console.log('Request canceled', thrown.message);
  } else {
    // 处理错误
  }
});
// 取消请求(message 参数是可选的)
source.cancel('Operation canceled by the user.');
  • CancelToken 挂载 source 方法用于创建自身实例,并且返回 {token, cancel}
  • token 是构造函数 CancelToken 的实例,cancel 方法接收构造函数 CancelToken 内部的一个 cancel 函数,用于取消请求
  • 创建实例中,有一步是创建处于 pengding 状态的 promise,并挂在实例方法上,外部通过参数 cancelToken 将实例传递进 axios 内部,内部调用 cancelToken.promise.then 等待状态改变
  • 当外部调用方法 cancel 取消请求,pendding 状态就变为 resolve,即取消请求并且抛出 reject(message)

总结

  • 为了支持 axios() 简洁写法,内部使用 request 函数作为新实例
  • 使用 promsie 链式调用的巧妙方法,解决顺序调用问题
  • 数据转换器方法使用数组存放,支持数据的多次传输与加工
  • 适配器通过兼容浏览器端和 node 端,对外提供统一 api
  • 取消请求这块,通过外部保留 pendding 状态,控制 promise 的执行时机

到此这篇关于一文掌握ajax、fetch和axios的区别对比的文章就介绍到这了,更多相关ajax、fetch和axios的比较内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 聊一聊数据请求中Ajax、Fetch及Axios的区别

    目录 Ajax介绍 Fetch介绍 Axios介绍 对比 几种方式的对比 总结 Ajax介绍 Ajax是XMLHttpRequest 对象提供了对 HTTP 协议的完全的访问,早期的项目,我们只能通过它向服务器端请求数据,包括Jquery封装的Ajax请求库也是基于它的封装 我们来看一下基于XMLHttpRequest对象去做一个Ajax请求的事例 // 通过XMLHttpRequest初始化一个Ajax请求实例 const xhr = new XMLHttpRequest(); // 设置超时

  • 一文掌握ajax、fetch和axios的区别对比

    目录 AJAX.Fetch.axios AJAX 创建AJAX AJAX的缺点: axios原理 axios的特点 axios常用的方法 put和patch的区别 axios相关配置 axios拦截器执行顺序问题 为什么axios中需要拦截器 为什么请求拦截2会在请求拦截1之前执行呢? Fetch.ajax与axios的区别 Fetch和Ajax比有什么优点 总结 axios源码分析 axios的执行流程 AJAX.Fetch.axios AJAX AJAX可以在不更新全局的情况下更新局部页面.

  • AJAX原理以及axios、fetch区别实例详解

    目录 AJAX原理 Promise封装Ajax JQ Ajax.Axios.Fetch的核心区别 JQuery Ajax Axios Fetch 补充:为什么要用axios? 总结 AJAX原理 Ajax的原理简单来说是在用户和服务器之间加了—个中间层(AJAX引擎),通过XmlHttpRequest对象来向服务器发异步请求,从服务器获得数据,然后用javascript来操作DOM而更新页面.使用户操作与服务器响应异步化. Ajax的过程只涉及JavaScript.XMLHttpRequest和

  • 关于vue中的ajax请求和axios包问题

    在vue中,经常会用到数据请求,常用的有:vue-resourse.axios 今天我说的是axios的post请求 github源文件及文档地址:[https://github.com/axios/axios] + 首先,引入axios CDN: <script src="https://unpkg.com/axios/dist/axios.min.js"></script> npm: npm install axios 并在全局的js中引入:import a

  • Vue为何弃用Ajax,选择Axios?ajax与axios的区别?

    目录 一.ajax与axios前言 二.ajax与axios的区别 三.Vue中axios的使用 一.发送并发请求 二.全局配置 三.创建axios实例 四.总结 axios是通过Promise实现对ajax技术的一种封装,就像jquery对ajax的封装一样,axios回来的数据是promise,ajax回来的数据是回调,axios比ajax更好用更安全.简单来说就是ajax技术实现了局部数据的刷新,axios实现了对ajax的封装:axios有的ajax都有,ajax有的axios不一定有.

  • 第一次在Vue中完整使用AJAX请求和axios.js的实战记录

    目录 零.AJAX 0.0 npm install express 0.1 express.js 0.2 GET-HTML 0.3 POST-HTML 一.导入模块 1.1方法一.下载axios.js,并放入vue工程plugins目录下 1.2方法二使用包管理器安装axios 1.3方法三直接引入CDN 二.实际应用 2.1以为和风天气API实践: 2.2数据接口如下: 2.3实现: 2.4完整Vue: 三.BUG修复 3.1 Can‘t resolve ‘axios‘ in ‘C:\vue\

  • 一文搞定MySQL binlog/redolog/undolog区别

    目录 MySQL binlog/redolog/undolog 的区别? bin log binlog刷盘时机 binlog日志格式 redo log 为什么需要redo log redo log基本概念 redo log记录形式 redo log与binlog区别 undo log MySQL binlog/redolog/undolog 的区别? 想和大家聊聊 InnoDB 中的锁机制,那么不可避免的要涉及到 MySQL 的日志系统,binlog.redo log.undo log 等,看到

  • Ajax常用封装库——Axios的使用

    Axios 是目前应用最为广泛的 AJAX 封装库 Axios的特性有: 从浏览器中创建 XMLHttpRequests 从 node.js 创建 http 请求 支持 Promise API 拦截请求和响应 转换请求数据和响应数据 取消请求 自动转换 JSON 数据 客户端支持防御 XSRF 使用axios时,需要通过使用script标签引入:https://unpkg.com/axios/dist/axios.min.js axios的中文网链接:Axios中文网 Axios API 向ax

  • vue2.0设置proxyTable使用axios进行跨域请求的方法

    这里请求的是知乎日报的api,由@izzyleung这位大神提供的,这是github地址. 在vue-cli构建的项目中先安装axios npm install axios -S 这里暂不考虑用vuex封装的方式,只讲在当前组件中直接使用. 先在<script>中引入 用prototype将axios添加为vue原生的属性,$ajax相当于axios的别名. 然后在要调用的方法或是钩子中请求,$ajax就是上面注册的axios,如果想直接用axios不想设置prototype也可以直接按官方的

  • Vue.js教程之axios与网络传输的学习实践

    前言 在学习了之前的路由vue-router和状态管理vuex之后,就应该是网络交互了.就学习尤大推荐的axios了.刚好本人对网络请求这块除了会get.put.post和delete这四个方法之外知之甚少,刚好补全上. 注意:Vue官方推荐的网络通信库不再是vue-resource了,推荐使用axios. 为何放弃vue-resource? 尤大的原话: 最近团队讨论了一下,Ajax 本身跟 Vue 并没有什么需要特别整合的地方,使用 fetch polyfill 或是 axios.super

随机推荐