导读
js以前是单线程,同一时间只能做一件事。
现在,js利用创建多线程解决了这个问题,也出现了同步和异步。
单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务,如果js执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉
<script> //结果是123,因为2不会等着3执行完再执行,而是异步执行,直接执行2,再执行3 console.log(1); setTimeout(function(){ console.log(3); },2000); console.log(2); </script>
同步解释
前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的。
异步解释
在做前一个任务的同时,还可以去处理其他的任务。
JS同步和异步
同步任务
同步任务都在主线程(执行栈)上执行,形成一个执行线。
异步任务
JS的异步是通过回调函数实现的。一般,异步任务有以下三种类型:
- 普通事件,如click、resize等
- 资源加载,如load,error等
- 定时器,如setInterval,setTimeout等
异步任务相关回调函数是添加到任务队列中(消息队列)。
比如setTimeout本身就是同步任务,但是它里面的回调函数是异步任务。
执行机制
- 先执行执行栈中的同步任务
- 遇到异步任务(回调函数)放入任务队列中
- 一旦执行栈中的所有的同步任务执行完毕,主线程(执行栈)就会按顺序再把异步任务队列中的异步任务进入执行栈,开始执行。
<script> //虽然没有延迟1秒,但结果还是123, //因为执行完1,去执行setTimeout,把回调函数放入任务队列中, //接着继续执行主线程里的2,最后再把任务队列中回调函数放入主线程里执行。 console.log(1); setTimeout(function(){ console.log(3); },0); console.log(2); </script>
由于主线程是不断的重复获得任务、执行任务、再获取任务、再执行,所以这种机制称为事件循环(event loop)
仔细分析下面的代码,因为不同的操作会有不同的结果,需要注意的是页面的点击,是不会触发这个事件,也就是不会把这个异步任务添加到任务队列里。
<script> console.log(1); document.onclick=function(){ console.log('c'); } console.log(2); setTimeout(function(){ console.log(3) },3000) </script>结果演示