一、什么是AJAX
Asynchronous JavaScript and XML:异步 JavaScript 和 XML
AJAX 不是一种新技术,而是用来描述一种使用现有技术集合的新方法 ——
包括:HTML 或 XHTML, CSS, JavaScript, DOM, XML, XSLT, 以及 XMLHttpRequest 。
是一种不用刷新整个页面便可与服务器通信的办法(通过AJAX与服务器进行数据交换,使网页实现局部更新)
问:AJAX最大的特点是什么?
答:AJAX可以实现局部刷新,能在不更新整个页面的前提下维护数据。让Web应用程序更为迅捷地回应用户动作,并避免了在网络上发送那些没有改变过的信息。
AJAX 包括以下几个步骤:
1)创建 XMLHttpRequest 实例
2)发出 HTTP 请求
3)接收服务器传回的数据
4)更新网页数据
二、工作原理分析
1、原理分析
AJAX是通过XmlHttpRequest对象向服务器发异步请求,从服务器获得数据,然后用 javascript 来操作DOM更新页面。(XMLHttpRequest -- 传说中的小黄人,是一个内建的浏览器对象,它允许使用 JavaScript 发送 HTTP 请求。 )
1)创建XmlHttpRequest对象 (小黄人相当于外卖小哥)
2)设置请求 (告诉小黄人服务器地址)
3)发送HTTP请求到服务器端 (小黄人去指定地址取外卖)
4)响应客户端请求
- 判断服务器的状态是否交互完毕
- 判断数据是否成功返回到客户端
- 处理服务器端响应的数据
2、AJAX返回的状态
XMLHttpRequest.readyState返回一个整数,表示实例对象的当前状态。该属性只读。它可能返回以下值:
0:未初始化,还没有调用send()方法
1:载入,已调用send()方法,正在发送请求
2:载入完成,send()方法执行完成,已经接收到全部数据
3:交互,正在解析数据
4:完成,数据解析完成,可以在客户端调用了
当状态为4的时候也就是接收数据完成的时候,也就是小黄人成功把外卖取回来了。
三、优缺点总结
优点:
1.页面无刷新,用户体验好。
2.使用异步方式与服务器通信,具有更加迅速的响应能力。
3.可以把以前一些服务器负担的工作转嫁到客户端,利用客户端闲置的能力来处理,减轻服务器和带宽的负担,节约空间和宽带租用成本。ajax的原则是“按需取数据”,可以最大程度的减少冗余请求及响应对服务器造成的负担。
4.基于标准化的并被广泛支持的技术,不需要下载插件或者小程序。
缺点:
1.不支持浏览器back按钮。
2.安全问题:AJAX暴露了与服务器交互的细节。
3.对搜索引擎的支持比较弱。
4.破坏了程序的异常机制。
5.不容易调试。
四、使用场景
内存中的数据编辑、页面导航、数据校验;
登陆失败时不跳转页面、注册时提示用户名是否存在、二级联动等场景
五、请求方式及对比
1、get
通过url传递参数,从指定的资源请求数据。以?分割URL和传输数据,多个参数用&连接。
2、post
向指定的资源提交要被处理的数据。
设置请求头,规定请求数据类型。
3、对比
相同点:两者本质上都是TCP链接
不同点
1、安全性
post更安全,post的参数放在请求体中,get的参数放在url上面,参数直接暴露在url中,所以不能用来传递敏感信息。
2、传输速度
get传输速度更快,根据传参决定的,post通过请求体传参,后台通过数据流接收,速度稍慢,而get通过url传参,可以直接获取。
3、传输文件大小
get一般限制在2~8K之间,更加常见的是1k以内;post一般无限制,默认为8M
4、浏览器缓存
(1)get请求会被浏览器主动缓存,而post不会,除非手动设置。
(2)get请求类似于查找的过程,用户获取数据,可以不用每次都与数据库连接,所以可以使用缓存。 post不同,post做的一般是修改和删除的工作,所以必须与数据库交互,所以不能使用缓存,因此get请求适合于请求缓存。
5、浏览历史记录
get请求参数会被完整保留在浏览器历史记录里,而post中的参数不会被保留。
6、产生数据包数量
get产生一个TCP数据包;post产生两个TCP数据包。
对于get方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据); 而对于post,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200(返回数据)
7、传参长度限制
get请求在url中传递的参数是有长度限制的,而post没。
注意:HTTP 协议未规定get和post的长度限制,get的最大长度限制是因为浏览器和web服务器限制了URL的长度,不同的浏览器和wed服务器,限制的最大长度不一样。
六、常用的AJAX请求库
下面两个库都是对xhr的封装
1、jQuery
比较重, 如果需要另外引入不建议使用
可能会产生回调地狱
2、Axios
是一个基于 promise 封装的网络请求库,它是基于 XHR 进行二次封装。轻量级, 建议使用。
-
封装XmlHttpRequest对象的AJAX
-
promise风格
-
可以用在浏览器端和node服务器端
Axios请求
//get请求
axios.get('/user?ID=12345')
.then(function (response) {
console.log(response.data);
})
.catch(function (error) {
console.log(error);
});
axios.get('/user', {
params: {
ID: 12345
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
post请求
axios.post('/user', {
firstName: 'Fred',
lastName: 'Flintstone'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
拓展fetch
fetch与xhr是并列关系,fetch是浏览器内置的原生函数,不用下载,直接使用,有浏览器就能用。也是 promise风格,可以解决回调地狱。
注:AJAX是异步请求的统称。Axios和Fetch都是利用promise封装实现的AJAX。只不过fetch是浏览器亲生的,axios是别人家的孩子。
//使用fetch发送网络请求(未优化)
search = () => {
fetch(`http://localhost:3000/api1/search/users2?q=${keyWord}`).then(
response => {
console.log('联系服务器成功了')
return response.json() //response.json()是一个promise实例对象
},
error => {
console.log('联系服务器失败了', error)
//错误则返回一个初始化状态的promise,中断promise
return new Promise(() => { })
}
).then(
response => { console.log('获取数据成功了', response) },
error => { console.log('获取数据失败了', error) }
)
}
//使用fetch发送网络请求(优化1)
search = () => {
fetch(`http://localhost:3000/api1/search/users2?q=${keyWord}`).then(
response => {
console.log('联系服务器成功了')
return response.json()
},
).then(
response => { console.log('获取数据成功了', response) },
).catch(
(error) => { console.log('请求出错', error) }
)
}
//使用fetch发送网络请求(优化2),最后统一处理错误
search = async () => {
try {
const response = await fetch(`http://localhost:3000/api1/search/users2?q=${keyWord}`)
const data = await response.json()
console.log('获取数据成功了',data)
} catch (error) {
(error) => {
console.log('请求出错', error)
}
}
}
七、跨域
首先了解同源策略
同源策略是浏览器一个非常重要的安全策略,基于这个策略可以限制非同源的内容与当前页面进行交互,从而减少页面被攻击的可能性。
什么是跨域
浏览器从一个域名的网页去请求另一个域名的资源时,域名、端口、协议其中任何一个不同,都是跨域。
造成跨域的本质原因在于AJAX引擎拦截响应,实际请求已经正常发出和响应了,只是响应回来时,被拦在“门外”。
解决跨域常见方案
1)CORS
CORS是目前主流的跨域解决方案,跨域资源共享(CORS) 是一种机制,它使用额外的 HTTP 头来告诉浏览器,允许浏览器向跨源服务器发出XMLHTTP Request请求,从而克服了ajax只能同源使用的策略。
实现cors的关键是服务器,只要服务器实现了cros接口,就可以跨域通信。前端只需正常发起ajax请求即可,成功的关键在于服务器 Access-Control-Allow-Origin 是否包含请求页面的域名,若不包含,浏览器将认为这是一次失败的异步请求,将会调用 xhr.onerror 中的函数。
详见:www.ruanyifeng.com/blog/2016/0…
2)JSONP
全称json with padding,解决老版本浏览器跨域数据访问问题,原理是web页面调用JS文件不受浏览器同源策略限制,所以通过script标签可以进行跨域请求。
流程如下: 首先前端设置好回调参数,并将其作为URL的参数,服务器端收到请求后,通过该参数获取到回调函数名,并将数据放在参数中返回,收到结果后因为是script标签,所以浏览器当做脚本运行。
3)增加中间代理服务器
解决跨域:增加中间代理服务器,该服务器与客户端保持同源。
代理服务器扮演中间人的角色,它没有AJAX引擎,所以可以与服务器正常通信并获取到服务器响应的数据,再通过转发的形式返回给客户端,由于与客户端同源,所以不会被拦截。