一文大白话讲清楚ajax(async javascript and xml)的原理和实现,以及封装一个异步ajax
1. ajax的原理
- ajax的全名叫async javascript and xml ,这样看不出来问题,我们翻一下,异步的javascript 和XML。
- 发现问题没,异步的。这个是关键,记住了,下边会有用,我们等重点将
- ajax的主要作用就是在不重新加载整个网页的情况下,与服务器交换数据,并且更新部分网页内容。
- 这就话反映出一个问题,说明以前跟服务器交换数据的时候会刷新整个页面
- 以前我们利用form表单提交的服务器请求的时候,会刷新整个网页。
- 这里大家可以想一下,为什么会刷新页面。其实实际上不是刷新,是覆盖。
- 浏览器向服务器发送请求,服务器处理完表单数据后,会返回一个新的页面,浏览器会加载这个新的页面,从而效果上导致了刷新。这也正是同步必要性导致的。假设不刷新页面,我们发送完请求,接下来干的事就不合理,因为我们是同步的,必须得等请求执行完我们才能下一步。咱们怎么控制呢,防止你请求完干这干那一些合理的事,我直接给你刷新。这就保持了同步性。
- ajax的牛逼之处在于,我不用返回新的页面,我把请求发给你,你把数据给我就行。这样的好处是显而易见的
- 比如我们在一个网页上,有很多的表单岗西刚写完,还没来得保存,结果触发了请求,整个页面刷新了,填写的信息都没了。这就很麻烦。
- 又或者页面本来就需要加载很多东西,很耗时,结果你老是反复刷新加载,这很耗费性能。
- 所以ajax不得不说,很牛逼
- 然后我们接着第一句讲,ajax是异步的,这个更牛逼,我们直到js的单线程的,不了解这些的看我的这篇文章 https://blog.csdn.net/xiaobangkeji/article/details/144730950 。
- 如果ajax不是异步,我们发送完请求以后,就得等着,等请求执行完,我们才能继续往下走,这就造成现线程阻塞了。不友好。现在是异步的了,我们发送完请求,该干啥继续干啥,如果请求的数据返回了,通知我们就行,我们去处理一下。
- 所以他的异步性不仅体现在不阻塞主线程执行,还体现在既然是异步的,那我们就可以并发执行。这就很牛逼。
2. ajax的实现
- ajax的主要实现分为4步
-
- 通过new XMLHttpRequest()创建XMLHttpRequest对象
-
- 通过open()方法建立连接
-
- 通过send()方法把数据发送给服务器
-
- 通过onreadystatechange事件监听readyState的状态,来判断请求是否完成,监听请求的状态
值 | 状态 | 说明 |
---|
0 | unset(未打开) | open()方法还未被调用 |
1 | opened (未发送) | send()方法还没有被调用 |
2 | headers_received(已获取响应头) | send()方法已经被调用,且响应头和响应状态已经返回 |
3 | loading(正在下载响应体) | 响应体下载中,responseTetxt中已获取部分数据 |
4 | done(请求完成) | 响应体下载完毕,整个请求结束,这时候我们要的所有数据就返回了 |
-
- 通过监听status的值,判断http状态码
- 要注意区分readyState和status,readyState是XMLHttpRequest对象的执行状态,而status是http状态码。
3. 手写封装ajax请求
function ajax(options){
let {url,method,data,dataType,async,timoeut}=options
const xhr=new XMLHttpRequest();
if(timoeut>0&& timoeut){
xhr.timeout=timoeut
}
return new Promise((resolve,reject)=>{
xhr.onreadystatechange=()=>{
if(xhr.readyState===4){
if(xhr.status===200){
resolve(xhr.responseText)
}else{
reject()
}
}
}
xhr.ontimeout=()=>{
reject()
}
xhr.onerror=()=>{
reject()
}
let _params=[];
let encodeData;
if(data instanceof Object){
for(let key in data){
_params.push(encodeURIComponent(key)+'='+encodeURIComponent(data[key]))
}
encodeDat=_params.join('&')
}
if(method==='get'||method==="GET"){
const index=url.indexOf('?')
if(index===-1)url+='?'
else if (index!==url.length-1)url+='&'
url+=encodeData
}
xhr.open(method,url,async)
if(method==='get'||method==='GET'){
xhr.send(null)
}else{
xhr.setRequestHeader("Content-Type",dataType)
xhr.send(data)
}
})
}
ajax({
url:'https://www.meiqianmei.com:8877/orders/latestList',
method:'get',
async:true,
timeout:2000,
data:{
}
}).then(
res=>console.log(res),
err=>console.log(err)
)