AJAX笔记
何为ajax
全称:Asynchronous JavaScript and XML。
用途: 在不重新加载页面的情况下发送请求给服务器。 接受并使用从服务器发来的数据。
常用概念
XMLHttpRequest
XmlHttpRequest是一个浏览器实现的一个接口,通过它发送一个ajax的请求(发出和接收HTTP请求),实现页面不刷新与服务端交互
var xhr = new XMLHtppRequest()
// 创建XMLHtppRequest 的实例
open( ) 方法
XMLHtppRequest 提供的open( )方法启动请求而不是立马发送,
以下是它的三个参数使用
- Method 请求方法:
GET
POST
DELETE
HEAD
OPTIONS
PUT
,通常大写 - url 请求url: 绝对路径和相对路径
- async 是否异步: 默认是true 表示异步
xhr.open("GET","/name.json")
请求头
在open() 之后设置,send()之前设置,重复设置只会 是添加而不是覆盖
xhr.setRequestHeader("Content-Type","text/plain")
发送请求 send()
发送请求方法可以没参数,特别是对GET请求
xhr.send()
以上是发送请求和数据给服务器
那么如何获得响应呢?
取得响应内容
完整的响应有状态码、响应头、响应主体组成,而XMLHttpRequest有对应的属性来使用,分别如下:
-
status
和statusText
分别是响应的状态和状态说明 例如200
、OK
-
getResponseHeader() 和 getAllResponseHeader()查询响应头,后者过滤掉cookie头,前者当接受到"set-cookie"和"set-cookie2"" 返回null
-
响应主体
responseText
响应主体的文本形式 和responseXML
响应主体的DOM XML形式
监听响应状态
前面的属性是在响应完成后取得,如何知道响应完成,就需要为请求加上监听以完成后得到通知,而这个可以通过XMLHttpRequest的 readystatechnge
事件来监听,因为XMLHttpRequest有个readyState ,而这个属性就是在请求和响应过程中的状态,每当这个属性值改变(状态发生改变)就会触发readystatechnge事件。所以在发起请求之前为它定义这个时间则可以完成监听。
var xhr = new XMLHttpRequest()
xhr.open("GET",url,true)
// 定义事件
xhr.onreadystatechange = function () {
// 判断是否响应完成
if(xhr.readyState == 4) {
// 响应完成后判断是否请求到数据或者 数据没有被修改
if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) {
// 输出响应的数据文本形式
console.log(xhr.responseText)
}
}
}
解析为什么监听事件放在发送请求之上,对于异步的事件来说,它不会同步被执行,而是进入了”等待执行状况“,由于请求也是异步的,所以本身代码是不会等待他们而是继续执行,事件比请求先进入栈中,所以在数据到来的过程中readyState会变化,而这个又会引发事件的效果,事件检测是否满足条件然后执行响应的回调函数。
提供readystate值:
0 | 未初始化 | 尚未调用open() 方法 |
---|---|---|
1 | 启动 | 已经调用open()方法,但未调用send()方法 |
2 | 发送 | 已经调用send()方法,但尚未接收响应 |
3 | 接收 | 已经接收到部分响应 |
4 | 完成 | 接收到全部响应,可被使用 |
发送请求xhr.send(data)
data 的数据类型可以有以下几种,在请求类型不是 GET
HEAD
下生效
FormData
,ArrayBuffer
,Blob
,Document
,DOMString
,FormData
,null
这些会让XHR对象自动为其设置相应的头部信息,具体参见你真的会使用XMLHttpRequest吗?
进度事件
-
loadstart
接收到响应数据的第一个字节触发
-
progress
在接收响应期间不断被触发
-
error
在请求发生错误时触发
-
abort
调用abort() 方法时被触发
- load
接收到完整响应数据时触发
因为load事件是在接收到响应后就会被触发,对于相应的状态不做检查,所以需要加上检查的判断语句,且使用onload始终触发事件对象时xhr对象,所以通用。
xhr.onload = function () {
if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) {
console.log(xhr.responseText)}
}
}
-
loadend
在通信完成或者触发 error、 abort、 load 事件后触发
超时
当请求长时间处于请求状态时,可以设置 timeout
来设置等待多少毫秒后终止请求,这个等待多少响应时间是由从send()后开始
var xhr = new XMLHttpRequest()
xhr.open('POST',url)
xhr.timeout = 1000 // 设置超时时间
// 当达到超时时间触发下面的事件
xhr.ontimeout = function() {
console.log("请求超时!")
}
xhr.onload = function () {
if(xhr.status>=200 && xhr.status<300 || xhr.status == 304) {
console.log(xhr.responseText)
}else {
console.log("error" + xhr.staus)
}
}
如何封装一个ajax
思路: 考虑到传入参数有:请求的类型,请求的主体,响应数据类型需不需要进行响应解码,比如如果是json类型需不需要对其解析( JSON.parse( ) ),成功后的回调函数,错误时的函数,还有对于请求的查询字段来说需要为键值对加上&
// 传入一个对象,包含所需的参数,必选的url、请求类型、
function ajax(opts) {
var url = opts.url
//请求类型
var type = opts.type || 'GET'
// 响应数据类型
var getData = opts.getData || 'json'
//成功回调函数
var onsuccess = opts.onsuccess || function () {}
// 失败回调函数
var onerror = opts.onerror || function () {}
// 查询字符串
var resData = resData || {}
var dataStr = []
for (key in resData) {
// 为查询字符串编码
key = encodeURIComponent(key)
resData[key] = encodeURIComponent(resData[key])
// 将其变为 Key1=value,key2=value2 格式存入dataStr
dataStr.push(key + '=' + resData[key])
}
// join()方法将其转换为 'Key1=value&key2=value2'的字符串
dataStr = dataStr.join('&')
if (type == 'GET') {
url += dataStr
}
var xhr = new XMLHttpRequest()
xhr.open(type, url, true)
xhr.onload = function () {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
if (getData === 'json') {
onsuccess(JSON.parse(xhr.responseText))
} else {
onsuccess(xhr.responseText)
}
} else {
//出错调用函数
onerror()
}
}
// 为请求出错事件设置函数
xhr.onerror = onerror
//判断如果是'POST'类型在send()上添加请求查询字符串
//如果是'GET'直接发送请求,因为查询字符串拼接到了url上
if (type === 'POST') {
xhr.send(dataStr)
} else {
xhr.send()
}
}
ajax({
url: 'http://api.douban.com/v2/movie/top250',
data: {
start: 0,
count: 10
},
onsuccess: function (ret) {
console.log(ret)
},
onerror: function () {
console.log('服务器异常')
}
})