经过昨天的一天AJAX的学习,今天对AJAX的起手写法已经烂熟于心了,那么现在开始新的AJAX的学习
异步
什么是异步?对它我的理解是,如果能直接拿到结果的,就是同步,如果不能直接拿到结果的,就是异步。
- 我们可以举个例子
比如我们去医院看病,往往需要先挂号,挂号这个操作是每次看病必不可少的,所以只能规规矩矩的跟着队伍挂号,这个就是同步的。但是当挂完号之后,什么时候去看病,是按照你挂号的号码来的,可能立刻就能看,可能要好久才能看,这个就是异步的,我无法立刻进行挂号的操作。
对于异步的这个操作,我们可以有两种操作的方法:回调和轮询,还是用举例来说:
对于回调,就是我们用微信接收通知,等到我们了手机会通知我们回去,对于轮询,就是我们自己人每过几分钟过去看一看,到我们了没有
异步用在AJAX
在AJAX中,我们在request.send之后,并不能直接得到response,必须等到readyState变成4之后,通过回调函数onreadstatechange,我们才能得到request,这就是一个异步操作用回调函数解决的案例
- 异步和回调的关系
异步任务需要在得到结果时通知JS来拿结果,怎么通知?可以让JS写一个函数给浏览器,异步任务完成时就调用这个函数,此时就能把结果作为参数传给函数。因为这个函数写出来是在别的方法执行完之后才进行的调用,所以这个函数是回调函数。
- 区别
异步需要回调函数来通知结果,但是回调不一定要用在异步内,比如forEach((a)=>{a += 1})
- 判断同步异步
- setTimeOut
- AJAX
- AddEventListener
- Promise.then
以上几个全是异步的,其他没说的都是同步的(还有好多,一下子想不起来了,具体情况具体分析)
通过回调来写一个摇骰子
function f1(x){
console.log(x)
}
function 摇骰子(fn){
setTimeOut(()=>{
fn(Math.random()*6+1)
},1000)
这个代码还可以简化
摇骰子(console.log)
此时,f1就是个回调函数,用来获得摇骰子方法中的值。
总结一下:
- 异步任务不能拿到结果
- 于是我们写一个回调给异步任务
- 异步任务完成时调用回调
- 调用的时候把结果作为参数传给回调
- 回调执行,将结果处理后返回
回调的参数过多
如果回调的参数不止一个,比如有两个,此时我应该怎么办?
那就搞两个回调fn(参数1=>{},参数2=>{}),或者接收两个参数,fn((参数1,参数2)=>{}),此时就会出现各种各样的解决方法,有人用第一种,有人用第二种。
而且过多的回调,会导致出现回调地狱,此时代码就变得十分难懂
getA(a=>{
getB(a,b=>{
b.forEach((c)=>{
c.map((x)=>{
x.id = a}).forEach((x)=>{x++})
})
})
})
这就是成堆的回调造成的回调地狱,这样很难进行错误的处理。 于是就有人抄袭了Promise,用Promise来解决这个问题,Promise到时候会再次做出一个总结,这边只给出封装的结果
ajax = (url,fn1,fn2)=>{
return new Promise((resolve,reject)=>{
const request = new XMLHttpRequest();
request.open('get',url)
request.send()
request.onreadystatechange = ()=>{
if (request.readyState === 4){
if (request.status >= 200 && request.status < 300){
resolve.call(null,request.response)
}else{
reject.call(null,request)
}
}
}.then((e)=>{
fn1()
},(e)=>{
fn2()
})
}
因为Promise的then返回一个Promise对象,所以可以链式调用,如果还要接着在上一个结果中调用函数,直接一个接下去用then就好了,非常的方便。但是这个封装还是很有问题的:我们无法指定请求头,比如说应对同源策略的的CORS。于是针对上述的问题,我们想到了运用库去解决——比如JQuery的ajax,以及现在常用的axios。jQuery的库现在已经很少前端在使用了,主要用的就是axios,所以我们这也开始直接用axios来解决问题。 axios的使用有点长,回头单独写一篇文章介绍吧