众所周知,JavaScript是一门单线程语言,等到上一个任务结束之后才会进行下一个任务。但是如果上一个任务迟迟没有结束,那下一个任务就会卡在原地无法动弹。
这时,我们就将所有的任务分为两类:同步任务和异步任务。
(1)同步和异步任务分别进入不同的执行"场所",同步的进入主线程,异步的进入Event Table并注册函数。
(2)所有同步任务都在主线程上排队依次执行,形成一个执行栈。
(3)主线程之外,还存在一个"任务队列"(task queue)。异步任务进入Event Table并注册函数,异步任务有了运行结果,就在“任务队列”之中放置一个事件。
(4)一旦主线程中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入主线程执行。
(5)主线程内的任务执行完毕为空,就会从"任务队列"中读取事件,这个过程是循环不断的,形成event loop(事件循环)。
以上也就是JS的初步执行机制(事件循环)。
那怎么才能判断出主线程的执行栈是否为空呢?
答:js引擎存在monitoring process进程,会持续不断的检查主线程执行栈是否为空,一旦为空,就会去Event Queue那里检查是否有等待被调用的函数。
一般情况,我们将异步任务又分为宏任务和微任务。
以上内容纯八股文,记住就好。
虽说宏任务与微任务都是异步任务,那它们的执行顺序也是一样的吗?
显而易见,答案是不一样。
事实是,微任务的执行时间比宏任务要早!
所以我们在执行完同步任务之后开始执行异步任务的顺序应该是:
通俗地讲,则是以下顺序:
执行同步代码 ==> 检查微任务并执行 ==> 执行宏任务1 ==> 检查微任务并执行 ==> 执行宏任务2 ==> 检查微任务并执行 ==> 执行宏任务3 …
这算是更精确的JS执行机制。
找个很经典的例题看一下吧。
setTimeout(function(){console.log('1')});new Promise(function(resolve){console.log('2');resolve();}).then(function(){console.log('3')});console.log('4');
执行结果: 2-4-3-1
上一篇:[Java·算法·中等]LeetCode53. 最大子数组和
下一篇: 宝宝应该喝什么水