什么Ajax

在现实Ajax之前,我们需要了解下什么Ajax?

Asynchronous JavaScript + XML(异步 JavaScript 和 XML), 其本身不是一种新技术,而是一个在 2005 年被 Jesse James Garrett 提出的新术语,用来描述一种使用现有技术集合的‘新’方法。

当使用结合了这些技术的 AJAX 模型以后, 网页应用能够快速地将增量更新呈现在用户界面上,而不需要重载(刷新)整个页面。这使得程序能够更快地回应用户的操作。

异步交互

接下来便要弄清楚什么是异步交互。

所谓异步交互,就是指指发送一个请求,不需要等待返回,随时可以再发送下一个请求。同步交互与异步交互的区别在于同步交互需要等待结果,而异步交互不需要等待。

举个简单的例子就是当点击某个按钮后,程序会去请求一些数据,而这个过程整个页面是不会刷新的。如下图所示,异步获取一言并且显示在页面中

e1137ef9-a733-41df-a6bb-af0e14452124

快速开始

一:核心对象

关于核心对象:https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest

核心对象是实现Ajax的关键所在,因为后边的一切方法都是基于这个核心对象进行操作。创建核心对象的方式固定,但需要注意的问题就是浏览器兼容问题(注意是IE)。

  • 谷歌、火狐、safari等浏览器

    使用new XMLHttpRequest()的方式进行创建

  • IE 7+

    使用new ActiveXObject("Msxml2.XMLHTTP")方式进行创建

  • IE 6-

    使用new ActiveXObject("Microsoft.XMLHTTP")方式进行创建

为了方便后期的使用,我会将其赋予window对象。并通过一个匿名函数,进行自动调用。

(function () {
  function createXMLHttpRequest() {
    var httpRequest;
    if (window.XMLHttpRequest) {
      // 适用于非IE浏览器
      httpRequest = new XMLHttpRequest();
    } else if (window.ActiveXObject) {
      //   适用于IE浏览器
      try {
        // IE 7+
        httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
      } catch (e) {
        try {
          //   IE 6-
          httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
        } catch (e) {}
      }
    }
    return httpRequest;
  }
  window.createXMLHttpRequest = createXMLHttpRequest;
})();

将创建核心对象的代码写入某个js文件后,我们在html文件中进行引用并初始化核心对象,将其打印。

image-20200829180920024

可以看到我们的核心对象成功的被打印出来了。

二:监听onreadystatechange事件

此事件可以通过核心对象readyState属性获取当前请求内容的状态,因此可以利用此状态来判断异步请求是否完成。

监听很简单,调用核心对象的onreadystatechange方法即可进行监听。

xhr.onreadystatechange = function () {}

监听完事件后还没完,我们首先需要通过核心对象的readyState属性进行判断当前异步提交的状态,其次无论服务器端返回结果是什么(404,服务器错误等),readyState属性最终都会变成4,因此需要通过status属性判断响应码。status属性可以判断响应结果是否成功或者失败。

关于readyState一共有五种状态,

  • 0

    未初始化

  • 1

    open()方法被调用

  • 2

    send()方法被调用

  • 3

    正在相应

  • 4

    相应完毕

而响应码指的是网络请求返回的状态码,通常有200,301,404,502等状态码。其中200表示请求成功,也就是我们需要判断的条件。

因此我们监听事件即可改为如下代码:

xhr.onreadystatechange = function () {
    if (xhr.status === 200 && xhr.readyState === 4) {
        // 当请求成功时执行的代码
    }
}

三:设置请求方式及地址

设置请求方式及地址用到的是核心对象的open方法。此方法共有四种传参形式。

xhr.open(method, url)
xhrReq.open(method, url, async);
xhrReq.open(method, url, async, user);
xhrReq.open(method, url, async, user, password);

但通常我们只会用第一种,其他三种可以参考MDN

这里我们以一言接口为例,演示GET请求。所以我们的open传递两个参数。

xhr.open('get', 'https://v1.hitokoto.cn/')

四:设置发送的数据

发送数据使用send()方法即可。其中传入的参数为需要发送的数据。但是并非所有方式都需要传入数据。

  • 请求方式为GET

    传入参数一定为null,而不是与将数据当作参数传入

  • 请求方式POST

    传入参数为需要提交的参数。格式为key=value&key=value.传参格式可以通过setRequestHeader属性进行修改。

    例如xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")

因为一言的接口请求是通过GET方式获取的,因此我们传送的参数为null

xhr.send(null)

五:处理数据

接下来只需要在第二步中在当请求成功时执行的代码部分进行编写处理代码。但是遇到一个问题,如何获得返回结果?通过核心对象responseText属性可以获取响应的内容。

  1. 先来打印下返回结果

    xhr.onreadystatechange = function () {
        if (xhr.status === 200 && xhr.readyState === 4) {
            // 当请求成功时执行的代码
            console.log(xhr.responseText);
        }
    }

    image-20200829215812773

  2. 处理数据

    很明显数据是一个字符串格式,那么为了方便处理,我们需要将他转换为JSON对象。

    xhr.onreadystatechange = function () {
        if (xhr.status === 200 && xhr.readyState === 4) {
            // 当请求成功时执行的代码
            var text = JSON.parse(xhr.responseText)
            console.log(text);
        }
    }

    image-20200829220108041

    可以看到,刚刚的数据已经变成了一个js的对象。我们只需要将这个对象取出来,进行处理即可。

    xhr.onreadystatechange = function () {
        if (xhr.status === 200 && xhr.readyState === 4) {
            // 当请求成功时执行的代码
            var text = JSON.parse(xhr.responseText)
            document.querySelector('p').textContent = text.hitokoto
        }
    }

    接下来页面中就显示了我们的一言。但是只有当刷新页面时才会更新一言,因此我们需要在做一个按钮,用来获取一言。

示例代码

在线地址:[https://tzk.acs.pw](https://tzk.acs.pw/2020-08/29/code/4. JS_ajax.html)

<!DOCTYPE html>
<html lang="en">

    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <script src="createXMLHttpRequestObject.js"></script>
    </head>

    <body>
        <button id="btn">点击获取</button>
        <p></p>
        <script>
            var btn = document.getElementById('btn')
            btn.addEventListener('click', function () {
                // 1. 创建核心对象
                var xhr = new createXMLHttpRequest()
                // 2. 监听异步请求状态
                xhr.onreadystatechange = function () {
                    if (xhr.status === 200 && xhr.readyState === 4) {
                        // 当请求成功时执行的代码
                        var text = JSON.parse(xhr.responseText)
                        document.querySelector('p').textContent = text.hitokoto
                    }
                }
                // 设置请求方式及地址
                xhr.open('get', 'https://v1.hitokoto.cn/')
                // 设置发送数据
                xhr.send(null)
            })

        </script>
    </body>

</html>