浏览器事件循环机制

日常开发我们通常都会用到回调函数,promise,setTimeout,我们有没有想过它们在浏览器中是怎样运行的,下面我们通过一个小例子来了解下

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是单线程语言,它只有一个调用栈,同一时刻只能做一件事,例如下面的代码

function mutltiply(a,b) {
    retrun a * b;
}
function square(n) {
    return mutltiply(n,n);
}
function printSqaure(n) {
    var squared = square(n);
    console.log(squared)
}
printSqaure(4);

main()、printSqaure(4)、square(n)、mutltiply(n,n)依次入栈

mutltiply(n,n)、square(n)、printSqaure(4)、main()依次出栈

最终控制台会输出最终结果:8

浏览器执行JavaScript时,事件循环可以保证这个线程可以独立运行,事件循环不断处理任务队列中的任务。所有任务分为同步任务异步任务两种,同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;异步任务指的是,不进入主线程,进入任务队列(Event Queue)的任务,只有任务队列通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

  1. 所有同步任务都在主线程上执行,形成一个执行栈。

  2. 主线程之外存在一个任务队列,只要异步任务有了运行结果,就会在任务队列之中放置一个事件

  3. 一旦执行栈中的所有同步任务执行完毕了,系统就会读取任务队列,对应的异步任务会结束等待状态,进入执行栈,开始执行。

  4. 主线程不断重复上面的第三步

在这里插入图片描述

任务队列中的任务分为宏任务微任务,宏任务一般是整体代码script,setTimeout,setInterval,微任务包含Promise。

每执行完一个宏任务,会执行完所有的微任务,执行完之后才会执行下一个宏任务

在这里插入图片描述

既然已经了解到这里了,那么我们可以回头看第一段代码,验证下上面的这些内容

  1. 遇到console.log(‘script start’);整体代码script作为宏任务压入执行栈,浏览器打印script start

  2. 遇到setTimeout,回调函数作为宏任务放入任务队列

  3. 遇到promise,回调函数作为微任务放入任务队列

  4. 遇到console.log(‘script end’);浏览器打印script end

  5. 整体代码(一个宏任务)执行完毕,开始执行微任务,浏览器打印promise1

  6. promise回调函数返回undefined,下一个回调函数作为微任务放入任务队列

  7. 执行下一个微任务,浏览器打印promise2

  8. 执行下一个宏任务setTimeout

    最终输出结果为:

    script start

    script end

    promise1

    promise2

    setTimeout

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值