通过阅读axios源码重新学习AJAX和XMLHttpRequest

今天单位活儿比较少,遂打开了axios源码阅读了一番。

照着axios的文档进行阅读,事半功倍。一边看源码,一边又顺着把AJAXXMLHttpRequest看了一遍,以下是我的收获。

由于XMLHttpRequest很长,我们一般将其简称为XHR,下面我将会使用简称进行书写。

1. axios和AJAX的区别

在写详细的文章之前,可能很多同学不是很清楚axiosajax的区别(清楚的同学可略过~),下面我们来简单讨论一下。

AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。

AJAX 不是新的编程语言,而是一种使用现有标准的新方法。

AJAX 是与服务器交换数据并更新部分网页的艺术,在不重新加载整个页面的情况下。

从本质上来讲,AJAX是一种技术的简称,使用它的目的就是要在不加载整个页面的情况下修改页面中某一部分的数据。

axios则是对这种技术的一种封装,将其不够好的地方加以改进,也更适合现代前端(MVVM架构)的使用场景。

之前看到过一个比喻:AJAX是飞机,axios是波音747。相信大家到现在应该能很好地理解两者之间的关系了。

2. axios

Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。

它有以下特点:(摘自axios官方文档)

  • 从浏览器中创建 XMLHttpRequests
  • 从 node.js 创建 http 请求
  • 支持 Promise API
  • 拦截请求和响应
  • 转换请求数据和响应数据
  • 取消请求
  • 自动转换 JSON 数据
  • 客户端支持防御 XSRF

通过axios的文档,我们可以知道,它内部也是通过XHR进行http请求的。所以这也就更好地印证了axios隶属于ajax。前者是后者更好地一种实现和封装。

那么我们不禁要问,为什么会有axios,它的出现解决了什么问题?以下我们挨个分析。

2.1 回调地狱

一说到回调,我们应该会想到两个东西:callbackPromise

相信在2017年左右参加工作的前端同学,可能对回调地狱这一情况不是特别了解,我也是了解了“前端历史”这一课之后,并亲自写了几个demo才深刻了解到这个。

在 Promise 为出现之前,我们用回调函数来编写异步程序,来满足日常开发的异步需求。随着前端的发展,代码的日益增多,逻辑逐渐复杂,大量使用回调函数的代码,让程序员开始头疼。代码可读性低、维护困难、大量前台回调函数,看的程序员是直接怀疑人生。

为了解决工程师们面临的这个问题,Promise 诞生了。它提供了一些 API,让工程师们可以用一种新的方式来编写异步程序。通过 then 方法来写异步程序执行成功后执行的代码,用 catch 方法来捕捉异常,而且可以链式调用。 函数地狱和回调函数造成的程序可读性差的问题,被解决了,小伙伴们又可以快乐的编程了。

axios的一个特点就是支持 Promise API,这让我们不用再使用回调函数去获取接口中返回的数据。尤其是在多个异步请求同时使用时尤其方便。

2.2 可以同时在浏览器和服务器上使用

2.3 支持非常多的人性化特性,可配置性强(封装的比较好)

  • 拦截请求和响应
  • 转换请求数据和响应数据
  • 取消请求
  • 自动转换 JSON 数据
  • 客户端支持防御 XSRF

3. AJAX

XMLHttpRequest 是 AJAX 的基础。

使用AJAX无非就是下面几步:

3.1 创建XHR对象

var xmlhttp = new XMLHttpRequest();

3.2 向服务器发送请求

xmlhttp.open("GET","http://demo.com/test",true);
xmlhttp.send();

xmlhttp.open()有3个参数:

参数 解释 类型
method 请求的类型 String get/post/put等
url 请求的路径 String
async 请求是否异步 Boolean true(异步)/false(同步)

与 POST 相比,GET 更简单也更快,并且在大部分情况下都能用。

然而,在以下情况中,请使用 POST 请求:

  • 无法使用缓存文件(更新服务器上的文件或数据库)
  • 向服务器发送大量数据(POST 没有数据量限制)
  • 发送包含未知字符的用户输入时,POST 比 GET 更稳定也更可靠

xmlhttp.send()有一个参数,只在post请求时使用。如下:

xmlhttp.open("POST","http://demo.com/test",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send("fname=Bill&lname=Gates");

setRequestHeader()用于设置请求头信息。send()方法中的参数为传递给服务器的请求参数。

3.3 服务器响应

要想获取服务器端的响应,我们需要监听onreadystatechange 事件

每当 readyState改变时,就会触发 onreadystatechange事件。readyState属性存有 XMLHttpRequest的状态信息。

下面是 XMLHttpRequest对象的三个重要的属性:

属性 描述
onreadystatechange 存储函数(或函数名),每当 readyState 属性改变时,就会调用该函数。
readyState 0: 请求未初始化 1: 服务器连接已建立 2: 请求已接收 3: 请求处理中 4: 请求已完成,且响应已就绪
status 200: “OK” 404: 未找到页面

onreadystatechange事件中,我们规定当服务器响应已做好被处理的准备时所执行的任务。

readyState等于 4 且status为 200 时,表示响应已就绪:

xmlhttp.onreadystatechange=function(){
  if (xmlhttp.readyState === 4 && xmlhttp.status === 200){
      // 处理业务 
  }
}

3.4 使用回调函数

如果存在多个 AJAX 任务,我们可以创建 XMLHttpRequest对象编写一个标准的函数,并为每个 AJAX 任务调用该函数。

通用的AJAX函数

function xhrRequest(method, url, callback) {
  var request = new XMLHttpRequest()
  request.open(method, url, true)
  request.send()

  request.onreadystatechange = function() {
    if(request.readyState === 4 && request.status === 200) {
      var res = request.responseText
      res = JSON.parse(res) // 在此处将返回的json字符串转为object数据
      callback(res)
    }
  }
}

具体的业务接口

function myFunction2(){
  xhrRequest('GET', 'http://demo.com/test', function(res) {
    console.log(res)
  })
}

4. 结语

虽然axios使用了很久了,但是一直没有往深里研究。今天也算是简单了解一下其原理,顺便把它用到的XHR也复习一遍。

你可能感兴趣的:(javascript,axios,AJAX,XMLHttpRequest)