跳转至

第12章 AJAX

第 12 章 AJAX

AJAX 的全称为 “Asynchronous JavaScript And XML”。AJAX 指的是异步的 JavaScript 和 XML。它是指一种创建交互式网页应用的网页开发技术。简单来说,AJAX 是一种用于创建快速动态网页的技术,它可以让开发者只向服务器端获取数据,需要注意的是,它是让开发者向服务器端获取数据,而不是图片、HTML 文档等。互联网资源的传输变得前所未有得轻量级和纯粹,这激发了广大开发者的创造力,使各式各样功能强大的网络站点,和互联网应用如雨后春笋一般冒出,不断带给人惊喜。本章内容主要包括 AJAX 渲染、同步与异步,以及 Axios 基本用法,响应 JSON 格式数据等。

12.1 AJAX 简介

2005 年,Jesse James Garrett 提出了 AJAX 这个新术语。AJAX 中的 A 是 Asynchronous 的首字母,表示异步的意思。也就是说,AJAX 可以发起异步的 HTTP 请求。AJAX 中的 X 是 XML 的首字母,XML 意为可扩展标记语言,最开始时作为后端向前端响应数据的文档格式,但是 XML 目前已经很少使用,在 AJAX 中,JSON 已经代替了 XML。

简而言之,AJAX 是使用 XMLHttpRequest 对象与服务器端通信的脚本语言。它可以发送及接收各种格式的信息,包括 JSON、XML、HTML 和文本文件。

试想,当用户触发一个 HTTP 请求到服务器端时,传统的 Web 应用交互会这样做:服务器端对请求进行处理,然后再返回一个新的 HTML 页面到客户端。每当服务器端处理客户端提交的请求时,客户都只能空闲等待。哪怕只是一次很小的交互,只需要从服务器端得到很简单的一个数据的情况,都要返回一个完整的 HTML 页面。而用户每次都需要浪费时间和带宽去重新读取整个页面。这样一来,由于每次应用的交互都需要向服务器端发送请求,应用的响应时间就依赖于服务器端的响应时间,从而浪费了大量带宽,而且导致了用户界面的响应速度比本地应用的更慢。

而 AJAX 与此不同,AJAX 应用可以仅向服务器端发送并取回必需的数据,同时在客户端采用 JavaScript 处理来自服务器端的响应。因为服务器端和浏览器之间交换的数据大量减少,所以用户就能看到响应更快的应用。同时很多的处理工作可以在发出请求的客户端机器上完成,因此对于速度而言,Web 服务器端的处理时间也减少了。

简单来说,使用 AJAX 技术,可以在页面不刷新或不跳转的前提下向服务器端发起 HTTP 请求,获取响应数据,将增量更新呈现在界面上。最后将 AJAX 技术的优势具体总结如下。

例如,搜索引擎页面中的搜索框就是一种典型的 AJAX 应用场景,如图 12-1 所示。

4aa91d17f4f492c287681430f1cb9109d0141db8728f4e5ad85178cab826c57a.jpg

当用户输入关键字之后,会通过 AJAX 技术向后端请求数据。在不刷新页面的前提下,获取与关键字关联的历史搜索词,并展现在页面中,如图 12-2 所示。

8e371c9c26c36526bd29d6ef7b1e0c2c9b1d3693472f285e6c2b0e1cbfdd7921.jpg

前面学习了 Thymeleaf 服务器端渲染,Thymeleaf 是一个现代化的、渲染 XML/XHTML/HTML5 等内容的、服务端的 Java 模板引擎。它的主要作用是在静态页面上渲染显示动态数据。渲染之后,浏览器的页面会整体刷新,呈现的是同步效果。如果想要实现局部刷新,那么需要借助本章学习的内容 ——AJAX 来进行渲染。相比服务器端渲染,AJAX 的请求是由 JavaScript 发出的,而不是浏览器,并且后台处理过程和服务器端渲染是一样的,只是响应结果直接返回给 JavaScript 代码,从而对页面进行 DOM 操作,因此局部更新不影响其他内容,这就是呈现的异步效果。服务器端渲染过程如图 12-3 所示。AJAX 渲染过程如图 12-4 所示。

a63e3fb80025e5306c5a74fe9f076ee2299d1ae27b99b7adc4062b9e16cef1ab.jpg

5264c02a4e1f03b9584f8bd9a7a3a4534904c402aeb5fcd345da0de85d3a56e6.jpg

同步和异步是一对相对的概念,那么什么是同步,以及什么是异步呢?下面将具体讲解。

12.2 同步与异步

因为 JavaScript 在同一时间只能处理一个任务,所有任务都需要排队,前一个任务执行完,才能执行下一个任务。如果前一个任务的执行时间很长,如执行 AJAX 操作或定时器操作时,后一个任务需要等它执行完毕才能向下执行,此时下面的任务就会被阻塞。拿定时器来说,当用户向后台获取大量的数据时,就需要等到所有数据都获取完毕才能进行操作,用户只能在那里干等着,这种阻塞对用户来说意味着 “卡死”,严重影响用户体验。在设计的时候,布莱登・艾奇就考虑到这个问题,将任务分为同步任务(synchronous)和异步任务(asynchronous)。

同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才会执行后一个任务。异步任务指的是,不直接进入主线程执行,而是进入任务队列,只有等主线程任务执行完毕,任务队列开始通知主线程,请求执行任务,该任务才会进入主线程。简单地说,同步任务执行之后,后面的任务必须等待同步任务得到计算结果并处理完成后才能执行;而异步任务在启动执行之后,后面的任务可以继续执行,当异步任务得到计算结果之后,会通知到主线程进行处理。

结合实际来说,如果在函数返回的时候,调用者还无法得到预期结果,而是要在将来通过一定的手段才能得到(如回调函数),这就是异步。例如,AJAX 操作。如果函数是异步的,发出调用之后,就会马上返回,但是不会马上返回预期结果。调用者不必主动等待,当被调用者得到结果之后,会通过回调函数主动通知调用者。

我们通过一个例子来描述同步和异步的区别,假如顾客去饭店吃饭,要点三道菜,分别是酸菜鱼、烤串和香菇炒油菜。若采用同步的方式进行处理,则顾客先向服务员点酸菜鱼,厨师先将酸菜鱼做好,然后吃完后再点烤串,烤串做好并吃完后再点香菇炒油菜,最后香菇炒油菜做好并吃完。整个过程中,不管上菜的时间有多久,都会等待上一道菜做好并吃完后,再点下一道菜,如图 12-5 所示。

71000a4a3c014c7426269334cce7b6b39ed54b4b02560fee678265cccb75dae4.jpg

c1cc17ed7ef072dec3e47af962af6b2772b5e2171c585e09d5efc246537daf50.jpg

若采用异步的方式进行处理,则顾客同时向服务员点酸菜鱼、烤串、香菇炒油菜,哪道菜做好就先上哪道菜。这样一来,即使后厨在制作其中一道菜时浪费了时间,也并不会影响另外两道菜的烹饪,如图 12-6 所示。做好哪道菜就上哪道菜,例如,上菜顺序如图 12-7 所示。

从前面的描述中可以得出结论:异步可以充分发挥计算机性能,使其不会因为执行一个耗时的任务导致后续代码被阻塞。可以想象,如果网页中需要获取一个网络资源,通过同步的方式获取,那么 JavaScript 需要等待资源完全从服务器端获取之后才能继续执行。这期间 UI 渲染也将停顿,这样的用户体验是非常不好的。而采用异步的方式获取,在下载网络资源期间,

JavaScript 和 UI 渲染都不会处于等待状态。

41f384ade3c21ce9adc71f9c8ad457717d2a6a3aab89633024c05e9c5a814f19.jpg

在 JavaScript 中,定时器、DOM 事件和 AJAX 等的执行方式都是异步的。需要注意的是,异步方式执行的 JavaScript 代码仍然是单线程运行的。当异步任务计算完成,得到结果并通知主线程之后,也需要等

待其他任务完成,主线程空闲时才能进行相关处理。

对比同步和异步可知,同步操作通常是串行的,多个操作按顺序执行,前面的操作没有完成,后面的操作就必须等待,如图 12-8 所示。而对于异步操作来说,多个操作相继开始并发执行,即使开始的先后顺序不同,但是由于它们各自是在自己独立的进程或线程中完成的,所以互不干扰,谁也不用等谁,如图 12-9 所示。

8f8a4609162d525cd2026dc6fd92f5c7ff34d98717d19653743ec1180e17e200.jpg

1be888b12d52120f507f4d5c3469ecf8e9efd2d3cb581494d3008a081bfe8463.jpg

在实际应用中,AJAX 指的是不刷新浏览器窗口、不做页面跳转、局部更新页面内容的技术。真正的前后端分离是前端项目和后端项目分服务器端部署,在这里可以先理解为彻底舍弃服务器端渲染,数据全部通过 AJAX 方式以 JSON 格式来传递。接下来会对 AJAX 应用展开详细介绍。

12.3 XMLHttpRequest 对象

AJAX 的技术核心就是 XMLHttpRequest 对象。当我们在 JavaScript 中发送一个 HTTP 请求或接收响应时,就会使用 XMLHttpRequest 对象。

XMLHttpRequest 对象是通过实例化 XMLHttpRequest () 构造函数的方式来创建的,示例代码如下。 var xhr = new XMLHttpRequest ();

那么,一个完整的 AJAX 是怎么通过 XMLHttpRequest 对象实现的呢?

其实使用 XMLHttpRequest 对象实现 AJAX 可以分为五步,具体如下。

(1)创建 XMLHttpRequest 对象。

(2)为 XMLHttpRequest 对象监听进度事件,由于是异步操作,等到接收响应数据后,事件才会触发。

(3)初始化请求并指定请求方式。

(4)发送请求并设置数据体。

(5)服务器端成功响应,触发进度事件,执行事件的回调函数,接收响应数据,并对响应数据进行相关处理。

明确使用 XMLHttpRequest 对象实现 AJAX 的五步后,先来整体 “感知” 发送 AJAX 请求并接收响应进行处理的案例。

HTML 文件的示例代码如下。

XMLHttpRequestTestServlet 示例代码如下。

运行代码查看页面效果,如图 12-10 所示。

2b723f6392072973e0e3a38930b0c8fe61c898a1828b02f14da43a2b35b89578.jpg

在此页面下按 F12 键,单击超链接发送请求,查看控制台响应数据,如图 12-11 所示。

XMLHttpRequest 一开始只是微软浏览器提供的一个接口,后来各大浏览器纷纷效仿也提供了这个接口,再后来 W3C 对它进行了标准化,提出了 XMLHttpRequest 标准。XMLHttpRequest 标准分 level 1 和 level 2 两个版本,level 2 版本是对 level 1 版本的升级和改进。简单地说,level 2 版本在原 API 的基础上新增了更多的 API。目前 level 2 版本中新增的 API 已经得到了各大浏览器的广泛支持。

140ef32fde89bfee0e8673cd9c4ca5c5f0b1fdde9bee8c65c0bc742f18e25233.jpg

XMLHttpRequest level 1 主要存在以下缺点。

level 2 版本在 level 1 版本的基础上进行了改进,XMLHttpRequest level 2 中新增了以下功能。

12.4 Axios 简介

使用原生的 JavaScript 程序执行 AJAX 的过程极其烦琐,为了解决 XMLHttpRequest 的 AJAX 请求封

装的复杂性,以及便于后续增加请求响应等拦截器的常用功能,还可以考虑使用第三方类库 Axios。

Axios 是目前最流行的前端 AJAX 框架。Axios 是一个具有独立开发功能且目标明确的请求类库,它基于 Promise,是一个既可用于浏览器又可以用于 Node.js 服务器端的 HTTP 请求模块。本质上它是符合最新 ES 规范,使用 Promise 实现的、原生 XHR 的封装。在服务端,它使用原生 Node.js 的 HTTP 模块实现;而在客户端,它则使用 XMLHttpRequest 对象实现。因为对于请求操作,Axios 进行了常用功能的封装,所以开发人员若想实现网络请求功能,则只需要直接安装使用它,就可以拥有它带来的诸多新的特性内容,主要包括以下几点。

12.5 Axios 入门案例

下面通过一个案例简单演示 Axios 的使用。在页面创建一个按钮,单击按钮发送异步请求,触发后台 Servlet 代码,并实现获取请求参数,在控制台输出。

采用 Axios 异步框架向后台发送请求的步骤如下。

HTML 页面如下,发送异步请求到服务器端(Servlet)。

创建 AJAXTestServlet,继承 HttpServlet,获取请求参数并返回响应数据。

运行代码,Axios 的入门案例首页如图 12-12 所示。

单击按钮,查看后端控制台,如图 12-13 所示。同时再次查看前端页面,如图 12-14 所示,成功接收到后台返回的响应数据。

c1af346f24c273fd9494466319a8274a4f138b48f413be17040ccf767f2162c5.jpg

a303e39d361af7405c1da77856a970ebfd837a61916280ae313f5695a2e758f2.jpg

cb36996d4bdbf0cfca6a10f5b4f8b35adad46b52d17aa68a551160715f5f67a8.jpg

12.6 Axios 基本用法

Axios 的使用方法与 Vue 类似,直接在页面导入对应的 *.js 文件即可。官方提供的借助