JavaScript:你了解js的事件循环吗?

事件循环

我们知道,JavaScript只支持单线程任务,即同一时间内只能执行一项任务。因此JS的底层巧妙地设计了一个执行栈,将事件执行顺序形成一个任务队列。


事件循环步骤如下:
  1. 所有同步任务都在主线程执行,形成一个执行栈
  2. 主线程之外有一个消息队列,只要异步操作执行完成(就是进入了回调),就到消息队列排队等候回调
  3. 同步代码,即栈中代码执行完后,就到消息队列中读取异步任务,结束异步人物的等待状态,并且放到执行栈中(并不是执行在队列执行),开始执行。
  4. 不停重复上面三步。

来看看最简单的例子:

console.log("第一项任务");
console.log("第二项任务");
console.log("第三项任务");

以上代码,JS将会按照顺序依次添加到任务队列(先进先出),在依次执行。


但如果我们修改一下?
console.log("执行整体环境")

setTimeout(() => {
    console.log("执行setTime")
},0)

new Promise((resolve) => {
    resolve()
}).then(function () {
    console.log("执行promise")
})

console.log("执行整体环境结束")

像上面的代码就不会像预期一样从头到尾直接执行出来:

执行整体环境
执行整体环境结束
执行promise
执行settime

那究竟是为啥呢?(黑人问号?)这就牵扯到下面的内容了。

宏任务与微任务

  • 宏任务主要包含:script( 整体代码)、setTimeout、setInterval、I/O、UI 交互事件、setImmediate(Node.js 环境)
  • 微任务主要包含:Promise、MutaionObserver、process.nextTick(Node.js 环境)。
  • 为什么要这么区分?原因是他们的执行顺序不同。
  1. 开始按照顺序,执行整体环境,算执行一个宏任务,把整体环境的代码调入执行栈,开始执行整体环境的代码。当遇到微任务注册的时候,把微任务进入微任务队列,遇到宏任务的时候进入到宏任务队列。
  2. 当执行完一次宏任务之后,会去查看微任务队列有没有东西,如果有东西,把微任务队列所有任务处理完毕
  3. 执行一下个宏任务
  4. 按照上面流程,一直进行循环。

也就是说,每当执行一次宏任务,都会去检查微任务队列是否有新的任务,把微任务队列清空才会继续下一次宏任务。
结合更复杂的代码理解:

console.log('script start');

setTimeout(function() {
  console.log('timeout1');
}, 10);

new Promise(resolve => {
    console.log('promise1');
    resolve();
    setTimeout(() => console.log('timeout2'), 10);
}).then(function() {
    console.log('then1')
})

console.log('script end');

//执行结果
script start
promise1
script end
then1
timeout1
timeout2
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值