Ajax快速上手和剖析
- 说到Ajax 可以说是一个老技术了而且代码也比较简单,本片从内部结构来讲解ajax
我们把ajax分为2个部分:请求部分and接收服务器响应
先看下面一段代码
发送请求
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AJAX(发送请求)</title>
</head>
<body>
<script>
// 涉及到 AJAX 操作的页面“不能”使用文件协议访问(文件的方式访问)
// AJAX 是一套 API 核心提供的类型:XMLHttpRequest
// 1. 安装浏览器(用户代理)
// xhr 就类似于浏览器的作用(发送请求接收响应)
var xhr = new XMLHttpRequest()
// 2. 创建桥接
xhr.open('GET', 'http://ajax.io/1/time.php')
// 3. 开始请求
xhr.send()
</script>
</body>
</html>
open(),第一个参数是请求方式,第二个参数是请求地址,当然这里写绝对路径也是可以的只是不推荐
打开浏览器F12 ,network我们可以看到我们的请求
当然图片上的其他内容有关HTTP协议传输方式我们这里暂且不谈
接收请求
接收请求,服务端要给我们返回一个参数我们这里就用PHP返回一个格林威治时间吧
<?php
echo time();
Ajax是默认异步传输的,所以我们要写一个函数来接收它
<script>
var xhr = new XMLHttpRequest()
xhr.open('GET', 'http://ajax.io/1/time.php')
xhr.send()
// 因为客户端永远不知道服务端何时才能返回我们需要的响应
// 所以 AJAX API 采用事件的机制(通知的感觉)
xhr.onreadystatechange = function () {
// 这个事件并不是只在响应时触发,XHR 状态改变就触发
// console.log(1)
if (this.readyState !== 4) return
// 获取响应的内容(响应体)
console.log(this.responseText)
}
</script>
方法/解析/兼容方案
- readyState 就是一个响应阶段当他等于4的时候说明已经接受完服务端传过来的响应体了 所以在它等于4的时候我们拿到的才是完整的数据
- responseText就是响应体就是服务端传过来的数据
当然上面的是基本的兼容写法,xhr.onreadystatechange = function () 我们是有内置的函数来替换掉的
也就是onload
他是—— HTML5 中提供的 XMLHttpRequest v2.0 定义的,所以在较老版本的浏览器可能不支持的,当然也有兼容写法,老版本ie 5/6 连new XMLHttpRequest() 都不支持 我们也有替代的方法那就是:ActiveXObject(‘1 Microsoft.XMLHTTP’)
var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('1 Microsoft.XMLHTTP')
- onload:是直接接收 readyState === 4 的的一个事件绑定
<script>
var xhr = new XMLHttpRequest()
xhr.open('GET', 'time.php')
xhr.send(null)
// onload 是 HTML5 中提供的 XMLHttpRequest v2.0 定义的
xhr.onload = function () {
console.log(this.readyState)
console.log(this.responseText)
}
</script>
执行过程:
我们在这里可能会疑惑这里的readyState 里面 4,既然有了4 那前面的 0 1 2 3 呢?我们来验证下
由于 readystatechange 事件是在 xhr 对象状态变化时触发(不单是在得到响应时),也就意味着这个事件会被
触发多次,所以我们有必要了解每一个状态值代表的含义
- 用一个表格来解释
- 时间轴来表示执行过程:
让我们用一段代码把执行过程打印出来吧:
<script>
var xhr = new XMLHttpRequest()
console.log(xhr.readyState)
// => 0
// 初始化 请求代理对象
xhr.open('GET', 'time.php')
console.log(xhr.readyState)
// => 1
// open 方法已经调用,建立一个与服务端特定端口的连接
xhr.send()
xhr.addEventListener('readystatechange', function () {
switch (this.readyState) {
case 2:
// => 2
// 已经接受到了响应报文的响应头
// 可以拿到头
// console.log(this.getAllResponseHeaders())
console.log(this.getResponseHeader('server'))
// 但是还没有拿到体
console.log(this.responseText)
break
case 3:
// => 3
// 正在下载响应报文的响应体,有可能响应体为空,也有可能不完整
// 在这里处理响应体不保险(不可靠)
console.log(this.responseText)
break
case 4:
// => 4
// 一切 OK (整个响应报文已经完整下载下来了)
console.log(this.responseText)
break
}
})
</script>
- 这段代码我们分别打印了4个阶段的responseText