JS开发者应懂的33个概念系列1&&17--调用堆栈 && 消息队列和事件循环

JS分为同步任务和异步任务,比如:

// 同步任务
console.log('start');
function first() {
    console.log('first');
    second();
}
function second() {
    console.log('second');
}
first();

// 异步任务
setTimeout(function() {
  console.log('setTimeout');
}, 0);
Promise.resolve().then(function() {
  console.log('promise1');
})
process.nextTick(function() {
    console.log('nextTick');
})
复制代码

执行栈是什么?

同步任务都在主线程上执行,形成一个执行栈

以上同步任务的执行过程图解:

消息队列是什么?

主线程之外,事件触发线程管理着一个消息队列,只要异步任务有了运行结果,就在任务队列之中放置一个事件。
一旦执行栈中的所有同步任务执行完毕(此时JS引擎空闲),系统就会读取消息队列,将可运行的异步任务添加到可执行栈中,开始执行。

小结1:

Promise.resolve().then(function() {
  console.log('promise1');
})
console.log('end');
复制代码

  • promise进入异步线程,执行任务,注册回调函数then;
  • 主线程执行同步任务:console.log('end');
  • 主线程代码执行完毕,执行回调函数:console.log('promise1');
  • 结束,输出顺序:end, promise1

宏任务(task)是什么?

浏览器为了能够使得JS内部task与DOM任务能够有序的执行,会在一个task执行结束后,在下一个 task执行开始前,对页面进行重新渲染(task->渲染->task->...)
属于宏任务的有:setTimeout,setInterval等与timer有关的

微任务(Microtask)是什么?

微任务是一个任务队列,这个队列的执行顺序是在清空执行栈之后。
属于微任务的有Promise,process.nextTick,ajax等
process.nextTick的概念和then不太一样,process.nextTick是加入到执行栈底部,所以和其他的表现并不一致,属于执行栈的一部分

重点来了:事件循环Event Loop是如何运行的?

从Event Loop谈JS的运行机制

运行机制:

  • 执行一个宏任务(栈中没有就从事件队列中获取)
  • 执行过程中如果遇到微任务,就将它添加到微任务的任务队列中
  • 同步任务执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行)
  • 当前主线程任务执行完毕,开始检查渲染,然后GUI线程接管渲染
  • 渲染完毕后,JS线程继续接管,开始下一个宏任务(从事件队列中获取)

小结2:

setTimeout(function() {
    console.log('setTimeout');
})
new Promise(function(resolve) {
    console.log('promise');
    resolve();
}).then(function() {
    console.log('then');
})
console.log('console');

复制代码

  • 先遇到setTimeout,那么将其回调函数注册后分发到宏任务Event Queue
  • 接下来遇到了Promise,new Promise立即执行console.log('promise');
  • then函数分发到微任务的消息队列中
  • 遇到console.log('console'),立即执行
  • then函数拿到主线程执行console.log('then')
  • 至此所有主线程上的同步任务和微任务完成,第一轮循环结束
  • 第二轮循环以之前放进去的宏任务setTimeout的回调函数开始,输出setTimeout
  • 第二轮循环结束,最终输出:promise, console, then, setTimeout

到此就结束了。

贴上一个非常经典的例子,检验一下自己吧!
console.log('1');

setTimeout(function() {
    console.log('2');
    process.nextTick(function() {
        console.log('3');
    })
    new Promise(function(resolve) {
        console.log('4');
        resolve();
    }).then(function() {
        console.log('5')
    })
})
process.nextTick(function() {
    console.log('6');
})
new Promise(function(resolve) {
    console.log('7');
    resolve();
}).then(function() {
    console.log('8')
})

setTimeout(function() {
    console.log('9');
    process.nextTick(function() {
        console.log('10');
    })
    new Promise(function(resolve) {
        console.log('11');
        resolve();
    }).then(function() {
        console.log('12')
    })
})
复制代码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值