JS的事件循环(Event Loop)

本文详细探讨了JavaScript中的事件循环机制,包括同步与异步任务、宏任务与微任务的区别,并通过代码示例解析了它们的执行顺序。重点讲解了setTimeout、Promise及其在事件队列中的处理方式,展示了不同任务类型的执行优先级。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JS中的事件分为两种,一种是同步,一种是异步。首先执行同步事间,然后执行异步事件。在异步事件的任务队列中,又分为宏任务和微任务,先执行微任务再执行宏任务。宏任务主要包括script( 整体代码)、setTimeout、setInterval、I/O、UI 交互事件、setImmediate(Node.js 环境);微任务主要包括Promise、MutaionObserver、process.nextTick(Node.js 环境)。下面看一段代码。

        window.onload = function () {
            console.log("script start")
            async function async1() {
                await async2()
                console.log("async1 end");
            }
            async function async2() {
                console.log("async2 end");
            }
            async1()
            setTimeout(function () {
                console.log("setTimeout");
            })
            new Promise(function (resolve) {
                console.log("Promise");
                resolve();
            }).then(function () {
                console.log("promise1")
            }).then(function () {
                console.log("promise2")
            })
            console.log("script end")
        }

打印结果为:

代码解释:首先我们将这个async1函数给转为promise(async/await本身就是promise的语法糖,可以相互转换),结果为

        window.onload = function () {
            console.log("script start")
            function async1() {
                new Promise(function (resolve) {
                    console.log("async2 end");
                    resolve();
                }).then(function () {
                    console.log("async1 end");
                })
            }
            async1()
            setTimeout(function () {
                console.log("setTimeout");
            })
            new Promise(function (resolve) {
                console.log("promise");
                resolve();
            }).then(function () {
                console.log("promise1")
            }).then(function () {
                console.log("promise2")
            })
            console.log("script end")
        }

执行顺序为:打印script start,async2 end,遇见promise.then放入微任务队列,遇见setTimeout放入宏任务队列,打印promise,遇见promise.then放入微任务队列,打印script end。也就是说首先打印script start、async2 end、promise、script end,然后执行微任务队列的,async1 end、promise1、promise2,最后打印宏任务setTimeout。

那么我把代码修改一下被?如下所示,又会打印什么?

        window.onload = function () {
            console.log("script start")
            function async1() {
                new Promise(function (resolve) {
                    setTimeout(function(){
                       console.log("async2 end")
                   },0)
                    resolve();
                }).then(function () {
                    setTimeout(function(){
                       console.log("async1 end")
                   },0)
                })
            }
            async1()
            setTimeout(function () {
                console.log("setTimeout");
            },0)
            new Promise(function (resolve) {
                console.log("Promise");
                resolve();
            }).then(function () {
                console.log("promise1")
            }).then(function () {
                console.log("promise2")
            })
            console.log("script end")
        }

首先打印同步事件,script strat、promise、script end,再打印微任务队列中的事件,peomise1、promise2,最后打印宏任务队列的事件,async2 end、setTimeout、async1 end。那么为什么setTimeout不是最后呢?因为 console.log("async2 end")这行代码在微任务队列中的宏任务队列,所以最后执行,倘若是打印setTimeout的时候给的给的时间大于0,那么setTimeout就还是在最后了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值