js 异步
js事件循环
javascript是一门单线程语言,既然js是单线程,js任务也要一个一个顺序执行。如果一个任务耗时过长,那么后一个任务也必须等着。但是如果我们想浏览新闻,新闻包含的超清图片加载却很慢,难道我们的网页要一直卡着直到图片完全显示出来?所以任务其实也分为两类:同步和异步。
同步和异步任务分别进入不同的执行”场所”,同步的进入主线程,异步的进入Event Table并注册函数。当指定的事情完成时,Event Table会将这个函数移入Event Queue。主线程内的任务执行完毕为空,会去Event Queue读取对应的函数,进入主线程执行。
上述过程会不断重复,也就是常说的Event Loop(事件循环)。
举个例子:
输出结果为:
执行顺序为:1 .console.log(1)进入Event Table并注册,计时开始。
2.执行console.log(2)。
3.2秒到了,计时事件timeout完成,console.log(1)进入Event Queue。
4.console.log(2)执行完了,console.log(1)从Event Queue进入了主线程执行。
假如console.log(2)执行的时间很长,就算console.log(1)的计时器时间到了,console.log(1)也不会执行,他必须等console.log(2)执行完毕才能执行。
除了广义的同步任务和异步任务,任务还有更精细的定义:
- macro-task(宏任务):包括整体代码script,setTimeout,setInterval
- micro-task(微任务):Promise,process.nextTick。
事件循环的顺序,决定js代码的执行顺序。进入整体代码(宏任务)后,开始第一次循环。接着执行所有的微任务。然后再次从宏任务开始,找到其中一个任务队列执行完毕,再执行所有的微任务。
举个例子:
执行结果:
分析一下执行过程:
这段代码作为宏任务,进入主线程。
先遇到setTimeout,那么将其回调函数注册后分发到宏任务Event Queue。
接下来遇到了Promise,new Promise立即执行。
遇到console.log(),立即执行。
整体代码script作为第一个宏任务执行结束,在Event Queue里面未发现微任务,不执行微任务。
第一轮事件循环结束了,开始第二轮循环,从宏任务Event Queue开始。发现了宏任务EventQueue中setTimeout对应的回调函数,立即执行。然后执行结束。
参考自:https://blog.csdn.net/haoaiqian/article/details/78622651