说到这个异步,首先就要弄懂,什么是同步?我们先来看看,同步和异步的区别在什么地方。
先来看看一个列子
console.log(100) setTimeout(function(){ console.log(200) },1000) console.log(300)
打印出来的顺序,100 300 200
这样子应该看明白了,这个程序是没有阻塞的..
一步一步往下执行,先打印出100,然后是是一个setTimeout事件,一秒钟之后打印出200.然后再打印出300.可以函数实际却不是这么执行的。
这就是一个异步的操作。setTimeout是一个异步的事件。我们来对比看看同步的
console.log(100) alert(200) console.log(300)
这就是一个同步的执行过程,首先打印出的100,然后就是弹出一个alert框,你要是一生都不点击确认框,那么这个300就永远也打印不出来。很明显,这就是一个阻塞的过程了
既然有了异步,那么这种异步的实际应用场合是什么样子的呢?
一句话,如果不想阻塞后面的操作,那就来一个异步吧。
主要场景如下
定时任务:setTimeout setInterval
网络请求:ajax操作,动态img请求
事件处理:click等事件
定时任务本文的一开始就介绍过了,万一是n秒之后呢,难道我要等着你么?想得美!
看看ajax的网络请求
console.log(100) $.get('../data.json',function(){ console.log(200) }) console.log(300)
这个网络请求,完全是要看网络怎么样,万一请求到了一万年之后,那怎么办?所以咯,我要异步异步异步!!!
console.log(100) var img=document.createElement('img') img.onload=function(){ console.log(200) img.src="../hahhahah.jpg" } console.log(200)
这个也是同理的,要是你的图片一直加载不出来,那不好意思,你继续,我先往下进行
console.log(100) document.getElementById('haha').addEventListener('clcik',function(){ console.log("终于点击了") }) console.log(200)
鬼知道你什么时候要触发这个点击事件,所以咯,还是一样的哈,啥时候点击了,啥时候执行你。不要影响到别人
难道就没人好奇么?为什么这个js要采取这样子的异步的模式
这就要说到单线程了,单线程!!!!!!!!!!!!
console.log(100) setTimeout(function(){ console.log(200) }) console.log(300)
先打印出100,然后呢?看到了setTimeout这个函数,哎呀妈呀,这个可是一个异步操作呀,关进小黑屋,先一边呆着去。继续执行,打印出300.好了,程序执行完了,去看看那个黑屋里面的货怎么样了,打印出200
什么是单线程?意思就是说,一次只能干一个事,就像我们人一样,你能一边学习,一边做饭吗?是同时同步,而不是,我上一秒学习,下一秒做饭,你这个是快速的上下文切换
还有一种情况,你一边听歌,一边做饭,那好吧,这个谁不会呢?我们这里指的是,你自己有意识的,需要付出心思的同时干两种事情
程序是单线程的,只能挨个的执行,这个没执行完,下一个免谈,要是碰见了耗时长的任务,如果是多线程的话,还能用另外一个线程来执行,但是单线程的情况下,那你就只能自认倒霉,你就这么耗着吧。
当然了,人类是聪明的,单线程的春天到了。因为我们想到了异步呀,你不是耗时很长会阻塞么,那你滚吧
那好,我滚了,但是我还是要执行的啊,那我什么时候执行呢?
这个时候,就要回调来处理
啥叫回调?
我的理解就是,你要在某个函数之后调用,不能抢了人家的顺序
function a(){ console.log("a") } function b(fn){ console.log("b") fn() } b(a)
像上面的这个函数,是不是我先调用了函数b,然后函数a才能执行啊,那你可以反驳,这样子好麻烦,我直接按顺序不也可以吗。看代码
function b(){ console.log("b") } function a(){ console.log("a") } b() a()
这样子不也是,先调用了函数b,然后再调用了函数a么?所以,这说明。回调函数真正的用处不在这儿,因为这两种写法没啥子大不了的区别
console.log(100) setTimeout(function(){ console.log(200) },1000) console.log(300)
那这个例子呢?setTimeout函数被关去了小黑屋,现在轮到他调用了,一秒之后,打印出了200。这就是回调函数的作用啊,100 200都打印出来了之后,又再过了一秒,才轮到这个函数执行,打印出了200
console.log(100) $.get('../data.json',function(data){ console.log(data) }) console.log(300)
看这个网络请求。100 300都打印出来了之后,我去处理这个ajax的请求,请求完了。获取到数据了,我总不能不管了吧,获取的数据总要取出来吧,这个时候,我定义了一个函数,就是用来当请求处理完了之后,用来处理后续的操作的,比如取得请求数据啥的。
总结:js是一个单线程的,要是遇见耗时的操作,不能白白就这么耗着啊,让这个操作先一边玩去,等我处理完了之后,再去处理这个耗时的操作,当我操作成功之后,用一个回调函数来去处理,至于什么时候请求完成,那就是别的知识点了。这个回调函数具体啥时候执行,就要看你具体是什么操作了