Ajax认识

Ajax 编程

本文主要包含以下内容:

  • Ajax 出现之前的世界
  • Ajax 基本介绍
  • Ajax 具体编码
  • 封装通用的 Ajax 方法

Ajax 出现之前的世界

在前面的文章介绍中,我已经为大家介绍了 HTTP 协议,我们的网络就是基于 HTTP 协议来进行通信的。可以说,因为网络的出现,改变了我们这个世界,通过网络,我们能够和世界各地的人实时的分享信息。

但是早期的网络通信,有一个最大的特点,就是每次请求都是一个完整的页面,所以在那个年代也不存在“ Web 应用”这个词,更多的是叫做“网站”,而“网站”的特点就是由多个页面组成的。

image-20211223095817235

从上图可以看出,页面与页面之间的跳转全靠 a 标签,每当用户点击一个 a 标签时,浏览器就会向服务器请求新的 HTML 页面。

客户端和服务器端唯一的交互就是通过 Form 表单,但是 Form 表单也不例外,还记得 Form 标签中的 action 属性么?那就是用来指定用户向服务器提交了信息后跳转到哪一个页面的,之后要跳转的那个页面也毫无意外是从服务器端返回的一个完整 HTML 页面。

在那个网速不佳的年代,重新刷新页面的成本是很高的,通常会导致在加载页面时屏幕变空白。

明白了 Ajax 出现之前的互联网形态后,你明显会感觉到那个时候太过原始,甚至还有点幼稚,所以那个时候的电商网站,也绝不会有购物车这个功能,基本就是看上某个商品后,提交购买商品信息表单然后就结束了整个购买流程。

和我们现在的互联网形态,显然有着天壤之别。

可以毫不夸张的讲,Ajax 的出现,为我们的互联网带来了一次全新的革命,如果将 Ajax 之前的互联网形态称之为 1.0 的话,那么 Ajax 的出现就是将互联网形态升级到了 2.0

Ajax 基本介绍

1999 年,微软公司在自家旗下的 IE5 中实现了一个叫 XMLHttp ActiveX 的控件。它最初是为 outlook Web 客户端而开发的,允许在后台使用 JavaScript 异步发送数据。随后其他浏览器也实现了这种技术,不过它仍然是一个相对未知的功能,很少使用。

2004 年和 2005 年,Google 公司相继推出了 GmailGoogle 地图。

Gmail

image-20211223100334346

Google 地图

image-20211223100238057

从这个时候开始,异步加载技术开始备受关注。这些 Web 应用程序使用的异步加载技术,通过更改页面部分内容而不进行全面刷新来增强了用户的体验。让用户感觉更像是一个桌面应用程序。

2005 年,Jesse James Garrett 发布了一篇文章,叫做“ Ajax : 一种新的 Web 应用程序方法”。

在文章中,Jesse James Garrett 提到了 Google 在其最近的 Web 应用程序中使用到的技术,而 Ajax 是实际上是几个单词的首字母缩写词,指的是该技术在使用的过程中所涉及到的不同部分,英语全称为 Asynchronous JavaScript and XML

  • Asynchronous:翻译成中文是异步的意思,当发送数据请求时,程序不必停下来等待响应。它可以继续运行,等待响应收到时触发事件。通过使用回调来管理这种过程,程序能够以有效的方式运行,避免了数据来回传输带来的延迟。

  • JavaScript:利用 JavaScript 我们可以接收来自服务器端返回的数据,并将这些数据通过 DOM 接口实时的更新到页面上。

  • XML:最开始术语 Ajax 被创造时,经常用 XML 文档来返回数据。但是实际上可以发送许多不同类型的数据。到目前为止,在 Ajax 中最常用的是 JSON,它比 XML 更轻量且更易于解析。JSON 还具备被 JavaScript 原生支持的优点,所以我们可以处理 JavaScript 对象,而不必使用 DOM 方法来解析 XML 文件。

Garrett 的文章发表以后,Ajax 的使用真正开始起飞。现在用户不必刷新页面,就可以在网页上看到新的内容。

常见的场景:

  • Google、百度地图

  • 购物车

  • 搜索联想

总之,只要客户端和服务器端发生了网络通信,但是页面并没有刷新的场景,基本上就是使用 Ajax 来实现的。

Ajax 实现了与服务器的异步通信、局部刷新页面,这是 Ajax 技术的核心所在。当然 Ajax 也不是只有优点没有缺点,关于 Ajax 的优缺点总结如下:

优点

  • 页面无刷新,在页面内与服务器通信,减少用户等待的时间,增强了用户体验。

  • 使用异步方式与服务器通信,响应速度快。

  • 可以把一些原本服务器的工作转接到客户端,利用客户端闲置的能力来处理,减轻了服务器和宽带的负担,节约空间和宽带租用成本。

  • 基于标准化的并被广泛支持的技术,不需要下载插件或者小程序。

缺点

  • 无法进行操作的后退,即不支持浏览器的页面后退。

  • 对搜索引擎的支持比较弱。

  • 可能会影响程序中的异常处理机制。

  • 安全问题。对一些网站的攻击,如 CSRF、XXS、SQL 注入等不能很好的防御。

Ajax 具体编码

了解了什么是 Ajax 后,接下来我们就要进入到实际的编码环节了。

使用原生的 Ajax 大致包括以下 4 个步骤:

  1. 创建 XMLHttpRequest 对象

  2. 发出 HTTP 请求

  3. 接收服务器传回的数据

  4. 更新网页数据

接下来我们来具体看一下每一个部分。

1. 创建 XMLHttpRequest 对象

创建一个 XMLHttpRequest 对象,也叫实例化一个 XMLHttpRequest 对象。因为 XMLHttpRequest( ) 本身是一个构造函数。

var xhr = new XMLHttpRequest();

IE5 是第一款引入 XMLHttpRequest 对象的浏览器。在 IE5IE6 中,XHR 对象是通过 MSXML 库中的一个 ActiveX 对象实现的。

var xhr = new ActiveXObject('Microsoft.XMLHTTP');

IE7+ 及其他标准浏览器都支持原生的 XMLHttpRequest 对象。为了应对所有浏览器,下面是创建 XMLHttpRequest 对象的兼容写法。

var xhr;
if(window.XMLHttpRequest){
	//  IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码
	xhr = new XMLHttpRequest();
} else {
	// IE6, IE5 浏览器执行代码
	xhr = new ActiveXObject( 'Microsoft.XMLHTTP' );
}

2. 打开连接

XMLHttpRequest 的实例对象提供了一个 open( ) 方法用来打开客户端与服务端之间的连接。该方法规定了请求的类型、请求的路径以及是否异步处理请求。语法结构如下:

xhr.open(method, url, async);

参数说明:

  • method:发送请求的方式,一般采用大写,例如 GET、POST

  • url:请求资源的位置路径。

  • async:控制是否异步处理请求。取值有 true(异步)和 false(同步),默认为 true。一般来讲,都会产用异步的方式来发送请求,不然 Ajax 将变得毫无意义。

3. 发送请求

XMLHttpRequest 的实例对象提供了一个 send( ) 方法用于客户端向服务端发送请求。

xhr.send();

请求参数

在向服务端发送请求的同时,是可以传递数据至服务端的。而请求方式的不同,数据的传递方式也不同。

GET 请求:传递的数据是跟在 open( ) 方法中的 url 后面。

xhr.open("GET","/users/isUser?username=zhangsan&pwd=123");
xhr.send(null);

POST 请求:传递的数据是放在 send( ) 方法的参数中。调用 send( ) 方法之前需要设定 Content-Type 头信息,模拟 HTTPPOST 方法发送一个表单,这样服务器才会知道如何处理上传的内容。

参数的提交格式和 GET 方法中 url 的写法一样。设置头信息前必须先调用 open( ) 方法。

xhr.open("POST","login.php",true);
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=UTF-8");
xhr.send("username=zhangsan&pwd=123");

POST 相比,GET 的请求方式更简单也更快,并且在大部分情况下都能使用。但是,在以下情况中,请使用 POST 请求:

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

4. 处理服务器返回的消息

一个完整的 HTTP 响应由状态码、响应头集合和响应主体组成。在收到响应后,可以通过 XHR 对象的属性来获取响应内容。

常用的属性有以下 4 个:

  • responseText: 作为响应主体被返回的文本(文本形式)

  • responseXML: 如果响应的内容类型是 text/xmlapplication/xml,这个属性中将保存着响应数据的 XML DOM 文档( document 形式)

  • statusHTTP 状态码(数字形式)

  • statusTextHTTP 状态说明(文本形式)

另外,第 2 步打开连接时,选择处理请求的方式不同,第 4 步处理服务器返回消息的方式也有所不同。

同步处理请求

当处理请求的方式为同步时,直接使用 XMLHttpRequest 的实例对象的 responseText 属性用来接收服务端返回的消息。

xhr.responseText;

但是不推荐使用同步处理请求的方式。使用这种方式会导致 JavaScript 代码要一直等到服务器响应就绪后才继续执行,如果服务器繁忙或缓慢,应用程序就会挂起或停止。但是对于一些小型的请求,也是可以的。

异步处理请求

当处理请求的方式为异步时,需要通过 XMLHttpRequest 的实例对象提供的 onreadystatechange 事件来监听并处理服务器返回的消息。

xhr.onreadystatechange = function(){
	// ...
}

从“请求准备发送”到最后“请求发送成功”,中间执行了一系列的任务,分别为:

  • 请求未初始化(0):即还没有调用 send( ) 方法;

  • 服务器连接已建立(1):即已调用 send( ) 方法,正在发送请求;

  • 请求已接收(2):即 send( ) 方法执行完成;

  • 请求处理中(3):即正在解析响应内容;

  • 请求已完成(4):且响应已就绪,即响应内容解析完成,可以在客户端进行调用了;

每执行一个任务,XMLHttpRequest 对象的状态值 readyState 都会发生改变。只要 readyState 属性发生改变时,就会触发 onreadystatechange 事件。

按照任务顺序,状态值 readyState 依次从 04 发生改变。

只有当状态值为 4 时,才表示请求完成。请求完成后,判断请求状态,状态码 status 为 200 时表示请求成功。只有请求完成并且成功了,才能处理服务端返回的消息。

xhr.onreadystatechange = function(){
    if(xhr.readyState == 4 && xhr.status == 200){
        var text = xhr.responseText;
        console.log( text );
    }
}

5. 完整代码

我们将上面分解的每一步整合在一起,就是一个完整的 Ajax 请求代码了。

// 1. 创建 XHR 对象
var xhr;
if (window.XMLHttpRequest) {
    //  IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码
    xhr = new XMLHttpRequest();
} else {
    // IE6, IE5 浏览器执行代码
    xhr = new ActiveXObject('Microsoft.XMLHTTP');
}

// 2. 打开连接
xhr.open("get", "/users/isPhoneExist?phone=12313212311"); // 第三个参数默认 true,表示异步;get 请求的参数跟在路径后面。

// 3. 发送请求
xhr.send(); // send 方法默认没有参数。
//xhr.send("phone=123&pwd=123"); // 请求是 post,且想要传参,send 方法才有参数。

// 4. 通过事件监听并处理服务器返回的消息
xhr.onreadystatechange = function () {
    // 服务器正常的响应数据回来
    if (xhr.readyState == 4 && xhr.status == 200) { 
        var text = xhr.responseText; // 得到的 text 是字符串
        DOMObject.innerHTML = text; // 处理响应数据
    }
}

封装通用的 Ajax 方法

通过上面的学习,我们已经掌握了如何创建一个 XHR 对象,并使用该对象来发送一个 Ajax 请求和服务器端进行通信。

但是我们也明显能感受到整个过程显得比较繁琐,里面还包含了一些和业务逻辑无关的兼容性的代码在里面,所以我们尝试来将这个 Ajax 请求进行一个方法的封装,封装完毕后,用户调用该方法传入必要的信息即可,无需再做兼容性的处理。

具体的封装示例如下:

// 辅助函数:该函数的功能就是将对象转为字符串
// {username:'zhangsan',age:18}  ====>  name=zhangsan&age=18
function toData(obj) {
    if (obj === null) {
        return obj
    }
    let arr = [];
    for (let i in obj) {
        arr.push(`${i}=${obj[i]}`); // ['name=zhangsan','age=18']
    }
    return arr.join('&');
}

// 封装的 ajax 函数 用于发送 ajax 请求
function ajax(obj) {
    // 确定提交的请求的方式
    obj.type = obj.type || 'get'
    // 确定提交的方式是同步还是异步
    obj.async = obj.async || true;
    // 设置提交数据的默认值
    obj.data = obj.data || null;
    let xhr = null; // 跑腿的人 
    // 1. 创建 xhr 对象
    if (window.XMLHttpRequest) {
        // 非 IE 浏览器
        xhr = new XMLHttpRequest();
    } else {
        // 是 IE 浏览器
        xhr = new ActiveXObject('Microsoft.XMLHTTP');
    }
    // 2. 请求对应的服务器地址(open) 如果有数据 向服务器发送数据(send)
    if (obj.type === 'get') {
        // 说明是以 get 形式来发送请求
        let url = obj.url + '?' + toData(obj.data) // 重构 url 将数据附加在 url 后面   test.php?name=zhangsan&pwd=123456
        xhr.open('get', url, obj.async);
        xhr.send(null);
    } else {
        // 说明是以 post 形式来发送请求
        xhr.open('post', obj.url, obj.async);
        xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
        xhr.send(toData(obj.data));
    }
    // 3. 进行状态的监听 将从服务器取回来的数据返回
    xhr.onreadystatechange = function () {
        if (xhr.readyState === 4 && xhr.status === 200) {
            // 说明 xhr 已经从服务器带着数据回来了
            obj.success(xhr.responseText);
        }
    }
}

在上面的代码中,我们封装了两个函数,一个是 ajax 函数,另一个是辅助函数 toData

辅助函数 toData 的作用是将将对象转为字符串,例如用户传入的是 {username:‘zhangsan’,userage:18},通过该函数可以转换为 name=zhangsan&age=18

ajax 函数就是我们具体发送 Ajax 请求的函数,里面封装了创建 XHR 对象的兼容性操作,以及根据用户不同的请求方式进行不同的处理操作。

通用的 Ajax 函数封装完毕后,之后我们要发送 Ajax 请求,整个过程就显得轻松多了,例如:

ajax({
    url : 'getStudent',
    type : 'get',
    success : function(data){
        render(JSON.parse(data).list);
    }
});

总结

  1. Ajax 并不是一门崭新的技术,而是当时所存在的几种技术的结合。

  2. 使用原生 Ajax 的步骤大致可以分为:

  • 创建 XMLHttpRequest 对象,
  • 发出 HTTP 请求
  • 接收服务器传回的数据
  • 更新网页的数据
  1. 根据浏览器的不同,创建 XMLHttpRequest 对象的方式也不同。

  2. 发送请求时要用到 open 方法和 send 方法。

  3. readyState 属性有 5 种状态值,一般我们只对值为 4 的时候采取相应的操作。


-EOF-

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值