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

猜你喜欢

转载自www.cnblogs.com/stdzz/p/11438720.html