浅析AJAX
AJAX
全称 Async JavaScript And XML
;主体思想就是使用 JS
发请求和收响应。
背景
在网页开发中,浏览器与服务器之间使用 HTTP
通信。浏览器输入一个地址,或者通过 form
表单发送数据。这时浏览器就会向服务器发出 HTTP
请求。
1999年,微软发布的 IE 5.0 首次引入该功能,但是没有能够引起重视。2004年,Gmail发布;2005年,Gmap发布。两个现象级产品正式把 AJAX
带入了人们的眼界。AJAX 一开始是用来处理 XML 的,直到后续出现的 JSON 发展到今天的 AJAX 可以处理如:HTML/CSS/JS/XML/JSON等。
2006年,W3C 发布了 AJAX 的国际标准。
步骤
AJAX 包括以下几个步骤:
- 创建 XMLHttpRequest 实例。
- 发出 HTTP 请求。
- 接收服务器传话的数据。
- 更新网页数据。
总体来说,浏览器创建了一个 XMLHttpRequest
函数,用这个函数可以构造出一个对象,JS 通过这个对象进行数据的发送与接收。这就是 AJAX。
AJAX 之所以用途如此之广,则还有一个特点:从服务器拿到数据后,并不会刷新整个网页,而是只更新网页里面的相关部分,从而不打断用户正在做的事情。
注意:AJAX 只能请求同源的网址(同源:同协议、同域名、同端口),如果是跨域请求,则需要做一些特别的处理,详情查看后续文章。
AJAX 完整例子:
// 创建实例
const request = new XMLHttpRequest()
// 建立连接
request.open('GET', '/xxx')
// 检测是否成功
request.onreadystatechange = function () {
if (request.readyState === 4) {
if (request.status >= 200 && request.status < 300) {
success()
} else {
error()
}
}
}
// 发送
request.send()
XMLHttpRequest 实例属性
readyState
readyState
返回一个整数,表示实例对象的当前状态。是只读属性,不可写。有如下值:
- 0,表示
XMLHttpRequest
实例已经生成。 - 1,表示
open()
方法已经被调用了。但是可以使用setRequestHeader()
方法来设置请求头。 - 2,表示
send()
方法被调用。 - 3,表示正在接收服务器返回的数据。
- 4,表示服务器返回的数据已经被完全接收,或者接收失败。
在通信的过程中,每当实例对象的状态变化,都可以触发 readyState
值的变化。这个值的变化则可以通过一个叫 readyStatechange
事件监听到。如下:
const request = new XMLHttpRequest()
if (request.readyState === 4) {
// 请求结束,可以处理数据
} else {
// 请求中
}
onreadystatechange
上文中我们提到过,如果要监听 readyState
的变化,则可以使用 readystatechange
事件实现监听。
response
XMLHttpRequest.response
属性表示服务器返回的数据体。可以是任何的数据类型,如:字符串、对象、二进制对象等,当然平时工作中用到最多的还是对象,具体的类型可以由 XMLHttpRequest.responseType
属性决定的。该属性时只读的属性。
responseType
XMLHttpRequest.responseType
属性表示服务器返回数据的类型,是一个字符串。这个属性时可写,可以在 open()
方法之后 send()
方法之前,设置该属性值,告诉服务器我需要什么样的数据。如果设置 responseType
为空字符串,则默认的类型则是 text
。可以有以下值:
- ”” 空字符串,表示服务器返回文本数据。
- “arraybuffer” 表示服务器返回二进制数组。
- “blob” Blob 对象,表示服务器返回二进制对象。(主要用在图像上)
- “json”, 返回
JSON
对象。 - “text”, 返回字符串。
“document” 返回文档。
const request = new XMLHttpRequest() request.open('GET', '/xxx') request.responseType = 'json' request.onreadystatechange = function () { if (request.readyState === 4 && request.states === 200) { success() } }
responseText
该属性接收服务器返回的字符串,为只读属性。只有请求完成后,该属性才会包含完整的数据。
responseXML
该属性返回从服务器接收到的 XML
或 HTML
文档对象,为只读属性。如果本次请求没有成功,或者收到的数据不是 XML
或 HTML
则返回的是 null
。
当然,如果要使用该属性的话是有限制条件的。必须把 HTTP
的回应头 Content-Type
设置为 text/xml
或 application/xml
。而且在发送请求时把 request.responseType
设置为 document
。当然如果返回头不是 text/xml
和 application/xml
又想通过此属性获取,则可以通过调用 XMLHttpRequest.overrideMimeType()
方法,强制进行 XML
解析。该属性成功解析后,就会形成一个 DOM 文档树。
status
该属性返回一个整数,表示服务器 HTTP
请求后的状态码。一般来讲如果通信成功,状态码则为 200,该属性时只读的,有如下常见的状态码:
- 200 表示正常,请求成功。
- 301,永久移动。
- 302,暂时移动。
- 304,MDN 解释,如果客户端发送了一个带条件的 GET 请求且该请求已被允许,而文档的内容(自上次访问以来或者根据请求的条件)并没有改变,则服务器应当返回这个状态码。304 响应禁止包含消息体,因此始终以消息头后的第一个空行结尾。
- 307,暂时重定向。
- 401,未授权。
- 403,禁止访问。
- 404,找不到指定的地址。
- 500, 服务器发生了错误。
只有状态码是 2xx
与 304
表示服务器返回是正常状态。
timeout 与 ontimeout
timeout
属性返回一个整数,表示多少毫秒后,如果请求仍然没有得到结果,就会自动终止。如果该属性为 0,就表示没有时间限制。ontimeout
属性用于设置了一个监听函数,如果发生了 timeout
事件,就会执行这个监听函数。例子如下:
const request = new XMLHttpRequest()
request.open('GET', '/xxx')
request.ontimeout = function () {
console.error('超时了')
}
request.onreadystatechange = function () {
if (request.readyState === 4 && request.status === 200) {
success()
} else {
error()
}
}
// 设置请求时间为10s
request.timeout = 10 * 1000
request.send()
upload
XMLHttpRequest
不仅可以发送请求,还可以发送文件,这就是 AJAX 文件上传。当我们发送一个文件后,可以通过 XMLHttpRequest.upload
属性得到一个对象,通过这个对象的事件,则可以得到上传文件的进展。主要事件有: loadstart
loadend
load
abort
error
progress
timeout
。
XMLHttpRequest 的实例方法
open()
该方法用于指定 HTTP
请求的参数,主要用到的参数是 method
与 url
。
method
: 表示HTTP
动词方法,比如:GET
/POST
/PUT
/DELETE
HEAD
等。在传参是最好是全大写或者全小写,切不可又大写又小写。-
send()
该方法用于实际发出的
HTTP
请求。它的参数是可选的,如果不带参数代表HTTP
请求中只有一个URL
没有数据体,如:GET
请求,如果带着参数,则表示在请求时带有数据信息体,如:POST
请求。 GET
请求示例:const request = new XMLHttpRequest() request.open('GET', '/xxx?id=' + encodeURIComponent(id)) ... request.send()
POST
请求示例const request = new XMLHttpRequest() const data = 'email=' + encodeURIComponent(email) + '&password=' + encodeURIComponent(password) request.open('POST', '/xxx')) ... // 指定为form表单方式提交 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded') xhr.send(data)
注意:所有的 XMLHttpRequest
的监听事件,都必须在 send()
方法调用之前设定。
formData
发送数据const formData = new FormData() formData.append('username', '小鱼儿') formData.append('email', 'xiaoyuer@126.com') formData.append('password', 'xxxxxx') const request = new XMLHttpRequest() request.open('POST', '/xxx') request.send(formData)
setRequestHeader
该方法用于设置浏览器发送的 HTTP 请求的头信息。必须在 open()
之后 与 send()
之前调用。如果该方法多次调用,设定的同一个字段,则每一次调用的值都会被合并成一个单一的值发送。
abort
该方法用于终止已经发出的 HTTP 请求。调用此方法后, readyState
变为 4 status
变为 0。
const request = new XMLHttpRequest()
request.open('GET', '/xxx')
setTimeout(() => {
if (request) {
request.abort()
request = null
}
}, 4000)
// 4s 后终止请求