这是今天一个朋友发给个人一个面试题,javascript
感受还挺有意思的,java
写个博客以供分享面试
先看看这个面试题目:promise
观察下面的代码,写出输出结果
异步
console.log('0') setTimeout(function () { console.log('1'); }); new Promise(function(resolve,reject){ console.log('2') resolve(3) }).then(function(val){ console.log(val) }) console.log(4)
输出结果: “0” “2” 4 3 “1”async
今天主要是分析为何输出结果是这样的?这就和 javascript
的执行机制密切相关了.函数
javascript
是一门单线程的语言, 这就意味着在执行代码的时候, 都只有一个主线程来处理全部的任务.oop
咱们都知道 javascript
包括同步代码和异步代码, 那么 javascript
是怎么处理这两种状况的呢?spa
场所
, 同步的进入主线程,异步的进入 Event Table
并注册函数Event Table
会将这个函数(回调函数)移入 Event Queue
Event Queue
读取对应的函数,进入主线程执行Event Loop(事件循环)
这里咱们引进了 Event Queue
事件队列这一律念. 全部异步操做的回调都会进入到这里. 而后等到主线程空闲, 就会从这里调取回调执行.线程
setTimeout
相信你们都有使用过, 能够延时执行而且是异步执行的.
可是有时候咱们获得的结果每每是代码实际执行的时间比咱们想要延时执行的时间要久。这又是为何呢?
这就和咱们以前所说的 Event Loop
有关了, 咱们能够来具体看下 setTimeout
的执行步骤:
setTimeout(function () { asyncFn() }, 1000); syncFn()
asyncFn
将异步执行函数放在 Event Table
, 而且开始计时syncFn
, 可是 syncFn
可能须要处理的内容不少, 执行时间超过 1
秒, 可是计时还在继续1
秒, setTimeout
延时完成, asyncFn
进入 Event Queue
事件队列, 可是主线程还在执行, 因此只能等待syncFn
执行完成, 此时 asyncFn
从事件队列中进入主线程执行因此有时候会出现代码实际执行时间比延时时间长的状况。
以前咱们说过异步任务会进入到事件队列中, 不一样类型的任务会进入到不一样的队列中, 好比宏任务会进入到宏任务队列中, 微任务会进入到微任务队列中.
微任务:promise
宏任务:setTimeout、setInterval、setImmediate
咱们只要记住 当当前执行栈执行完毕时会马上先处理全部微任务队列中的事件,而后再去宏任务队列中取出一个事件。同一次事件循环中,微任务永远在宏任务以前执行
这时候咱们就能够解释一开始的代码执行结果了:
setTimeout
, 回调进入到宏任务队列上Promise
, 当即执行, then
函数进入到微任务队列then
, 执行setTimeout
, 执行setTimeout
执行结束, 检查,不存在其余, 结束.
以上。