2005年,Adaptive Path 公司的Jesse James Garrett 发明了Ajax这个词,用于概括异步加载页面内容的技术。以前,web应用都要涉及大量的页面刷新:用户点击了某个链接,请求发送回服务器,然后服务器根据用户的操作再返回新页面。即便用户看到的知识页面中的一小部分有变化,也要刷新和重新加载整个页面,包括公司标志,导航,头部区域,脚部区域等。
使用Ajax就可以做到只更新页面中的一小部分。其它内容——标志、导航、头部、脚步,都不用重新加载。用户仍然像以前一样点击链接,但这一次,已经加载的页面中只有一小部分区域会更新,而不必再次加载整个页面了。
Ajax的主要优势就是对页面的请求以异步方式发送到服务器。而服务器不会用整个页面来相应请求,它会在后台处理请求,与此同时用户还能继续浏览页面并与页面交互。你的脚本则可以按需加载和创建页面内容,而不会打断用户的浏览体验。利用Ajax,web应用可以呈现出功能丰富,交互敏捷,类似桌面应用般的体验,就像你使用谷歌地图的感觉一样。
Ajax核心数据:
Ajax技术的核心就是XMLHttpRequest对象。这个对象充当着浏览器中的脚本与服务器之间的中间人的角色。以往的请求都由浏览器发出,而JavaScript通过这个对象可以自己发送请求,同时也自己处理响应。
服务器在向XMLHttpRequest对象发回响应时,该对象有许多属性可用,浏览器会在不同阶段更新readyState属性的值,它有5个可能的值:
0、未初始化
1、正在加载
2、加载完毕
3、正在交互
4、完成
只要readyState属性的值变成了4,就可以访问服务器发送回来的数据了。
访问服务器发送回来的数据要通过两个属性完成。一个是responseXML属性,用于保存Content-Type头部中指定为“text/xml”的数据,其实是一个DocumentFragment对象。你可以使用各种DOM方法来处理这个对象。而这也是XMLHttpRequest这个名称里有XML的由来。
例子:
let ajax = new XMLHttpRequest()//初始化XMLHttpRequest构造函数
ajax.open('get','http://baidu.com')//设置参数
ajax.send()//发送给http://baidu.com
ajax.onreadystatechange = ()=>{//监听状态的改变
if (ajax.readyState === 4){//请求体已全部传送完成
if (ajax.status >= 200 && ajax.status < 300){//判断状态码
let data = ajax.responseText//拿到json字符串信息
let obj = JSON.parse(data)//转成js对象
} else if (ajax.status >= 400){
console.log('请求失败了')
}
}
}
注意:
在使用Ajax时,千万要注意同源策略。使用XMLHttpRequest对象发送的请求只能访问与其所在的HTMl处于同一个域中的数据,不能向其它域发送请求。此外,有些浏览器还会限制Ajax请求使用的协议。比如在谷歌浏览器中,如果你使用file://协议从自己的硬盘里加载example.txt文件,就会看到“Cross origin requests are only supported for HTTP”(跨域请求只支持HTTP协议) 的错误消息。如果一定要跨域访问,也可以办到,需要在被请求的服务器上配置这么一段话:
response.setHeader('Access-control-Allow-Origin', '*')
//*号代表可以接受任何网站的访问,可替换成某一个具体的网址
ajax请求与响应总结:
GET /xxx HTTP/1.1
HOST: jack.com:8002
Content-Type: application/x-www-url-encoded
'get没有第四部分,如果是post请求则有这一部分'
1. JS可以设置任意请求header吗?
第一部分 request.open('get', '/xxx')
第二部分 request.setHeader('content-type','x-www-form-urlencoded')
第三部分 空格
第四部分 request.send('a=1&b=2')
2. JS可以获取任意响应header吗?
第一部分 request.status / request.statusText
第二部分 request.getResponseHeader() / request.getAllResponseHeaders()
第三部分 空格
第四部分 request.responseText
模仿jQuery封装ajax的例子:
//封装XMLHttpRequest
window.jQuery.ajax = ({url, method, body, success, fail}) => {
let ajax = new XMLHttpRequest;
ajax.open(method, url)
ajax.onreadystatechange = () => {
if (ajax.readyState === 4) {
if (ajax.status >= 200 && ajax.status < 300) {
success.call(undefined, ajax.responseText)
} else if (ajax.status >= 400) {
fail.call(undefined, ajax.responseText)
}
}
}
ajax.send(body)
}
//点击传参发送ajax
myButton.addEventListener('click', (e) => {
window.jQuery.ajax({
url: '/go_api',
method: 'get',
success: (e) => {
console.log(e, '成功了')
},
fail: (e) => {
console.log(e, '失败了')
}
})
})
用Promise重构ajax:
window.jQuery.ajax = ({url, method, body}) => {
return new Promise(function (resolve, reject) {
let ajax = new XMLHttpRequest;
ajax.open(method, url)
ajax.onreadystatechange = () => {
if (ajax.readyState === 4) {
if (ajax.status >= 200 && ajax.status < 300) {
resolve.call(undefined, ajax.responseText)
} else if (ajax.status >= 400) {
reject.call(undefined, ajax.responseText)
}
}
}
ajax.send(body)
})
}
//点击传参发送ajax
myButton.addEventListener('click', (e) => {
window.jQuery.ajax({
url: '/go_api',
method: 'get',
}).then(
(res)=>{console.log(res,'成功')},
(err)=>{console.log(err,'失败')}
)
})