前言
先上一段代码,可以根据自己之前对JS执行机制的理解,进行分析
console.log('script start');
setTimeout(function() {
console.log('setTimeout');
}, 0);
Promise.resolve().then(function() {
console.log('promise1');
}).then(function() {
console.log('promise2');
});
console.log('script end');
答案:
script start
script end
promise1
promise2
setTimeout
如果自己的答案和上面的答案有出入,请继续阅读
基本概念的阐述
调用堆栈
- JavaScript有一个单独的调用堆栈,负责执行JS代码,当即将执行一个函数时,此函数就会被添加到调用堆栈中,当此函数执行完,则会出栈。
事件表
- 每次调用setTimeout函数或执行异步操作时,都会将其添加到事件表中,事件表负责记录每个事件完成后执行的回调函数,并监听事件,事件完成后会把事件的回调函数发送到事件队列。
事件队列
- 事件队列接收来自事件表的回调函数,并根据顺序执行。事件队列中存储两种任务: 微任务和宏任务
在当前的微任务没有执行完成时,是不会执行下一个宏任务的。
这里有两种说法,一种说法把刚开始执行的整体JS代码认为是一个宏任务,先执行整体JS代码这一个宏任务,执行完成后,再执行微任务列表中的所有微任务,所以认为先执一个行宏任务再执行所有微任务
另外一种说法没有把刚开始的JS代码当做宏任务,所以起始执行的是微任务,所有微任务执行完再执行宏任务,认为先执行微任务再执行宏任务
其实两种说法的核心是一样的,都是执行一个宏任务 执行所有微任务
事件循环
- 事件循环就是一个持续运行的进程,用于检查调用堆栈是否为空。将我们上面所述连接起来,并循环执行。
JS执行机制
console.log('script start');
setTimeout(function() {
console.log('setTimeout');
}, 0);
Promise.resolve().then(function() {
console.log('promise1');
}).then(function() {
console.log('promise2');
});
console.log('script end');
再次分析此段代码
最初始状态:JS调用栈为空,任务队列中宏任务队列有script代码块就绪
第一步:检查调用栈为空,将宏任务script入栈,开始向下执行
第二步:当遇到异步操作时,执行异步,并将异步事件与其回调函数注册到事件列表,同步代码继续执行
第三步:当事件表监听到异步事件已经完成,将其事件的回调函数入队(任务队列)
第四步:检查到调用栈为空,先将微任务依次入栈(调用堆栈)执行,微任务列表为空时,将宏任务入栈(调用堆栈)执行
更多关于JS执行机制的理解请点击下面链接,有动画效果有助于理解 特别推荐
Tasks, microtasks, queues and schedules
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。