JS事件循环机制

  let t0 = Date.now();
  let t1 = 0;
  let t2 = 0;
  let t3 = 0;
  let t4 = 0;
  f1();
  f2();

  function timerFn() {
    console.log('bbbbb');
    t3 = Date.now();
    console.log('timerFn:', (t3 - t0) / 1000)
  }
  function f1() {
    setTimeout(timerFn, 1000);
  }

  function f2() {
    for (let i = 0; i <= 1000000000; i++) {
      if (i === 1000000000) {
        console.log(i)
      }
    }
    t2 = Date.now();
    console.log('f2():', (t2 - t0) / 1000)
  }

打印结果如下:

1000000000
f2(): 2.045
bbbbb
timerFn: 2.055

事件循环机制

在这里插入图片描述

js刚开始执行时,执行栈中只有 f1() 和 f2() 两个任务待执行。

在执行 f1() 时,因为调用了 setTimeout,所以开启了定时器线程开始计时,在计时1s 后,将 timerFn 放入任务队列,此时 timerFn 只是在任务队列中等待,并未进入执行栈中。

待 f2() 执行完毕,执行栈处于空闲状态,此时任务队列中的 timerFn 会被推入到执行栈中,然后开始执行 timerFn

<think>嗯,用户想了解JavaScript事件循环的工作原理,包括机制、原理和图解。好的,首先我需要回忆一下事件循环的基本概念。JavaScript是单线程的,这意味着它一次只能执行一个任务。但是,为了处理异步操作,比如定时器、网络请求或者事件监听,就需要事件循环机制来管理这些任务的执行顺序。 根据引用[2],事件循环是JavaScript实现异步的关键。用户可能想知道单线程如何同时处理多个任务。这里需要解释调用栈、任务队列和事件循环之间的关系。同步代码会直接执行,而异步任务会被放到任务队列中,等待调用栈清空后再执行。 接下来,引用[4]提到事件循环模型是基于事件驱动的,浏览器生成的事件会被放入事件队列。这里可能需要区分宏任务和微任务。比如,setTimeout属于宏任务,而Promise的then回调属于微任务。微任务的优先级高于宏任务,所以事件循环在处理宏任务之前会先清空微任务队列。 引用[5]中的图解应该可以帮助用户理解执行顺序。比如,先执行同步代码,遇到异步任务就注册回调,然后继续执行同步代码。等同步代码执行完后,检查微任务队列,执行所有微任务,再执行一个宏任务,如此循环。 用户可能需要具体的例子来说明这个过程。例如,同步代码、Promise、setTimeout的执行顺序。这时候可以用一段代码示例,分步骤解释执行过程。同时,引用中的资料可以作为理论支持,比如引用[1]提到事件循环对编写高效异步代码的重要性,说明理解这一机制的实际应用。 另外,需要注意Node.js事件循环与浏览器的区别,如引用[3]提到两者的区别。但用户的问题可能主要集中在浏览器环境,所以可以简要提到Node.js的不同,但主要详细说明浏览器的机制。 最后,用户可能需要一个清晰的总结,将整个过程步骤化,便于记忆和应用。同时,相关问题可以引导用户深入理解,比如事件循环的应用场景、宏任务和微任务的区别,以及如何避免阻塞事件循环等。</think>### JavaScript事件循环机制详解 #### 1. 核心架构 JavaScript采用单线程+事件循环模型实现异步处理。执行顺序遵循**同步代码 > 微任务 > 宏任务**的优先级规则[^2][^5]。 #### 2. 核心组件图解 ``` ┌───────────────────────┐ │ Call Stack │<─────执行上下文 └──────────┬────────────┘ │ ▼ ┌───────────────────────┐ │ Web APIs │<─────浏览器提供的API └──────────┬────────────┘ │ ▼ ┌───────────────────────┐ │ Task Queue(宏任务) │ ├───────────────────────┤ │ Microtask Queue │ └──────────┬────────────┘ │ ▼ ┌───────────────────────┐ │ Event Loop │<─────循环检测机制 └───────────────────────┘ ``` #### 3. 执行流程(含代码示例) ```javascript console.log('1'); // 同步 setTimeout(() => console.log('2'), 0); // 宏任务 Promise.resolve().then(() => { console.log('3'); // 微任务 setTimeout(() => console.log('4'), 0); // 嵌套宏任务 }); console.log('5'); // 同步 ``` **执行顺序解析**: 1. 执行同步代码:输出`1`和`5` 2. 处理微任务队列:输出`3`,注册新宏任务`4` 3. 执行第一个宏任务:输出`2` 4. 执行新产生的宏任务:输出`4` 最终输出顺序:`1 → 5 → 3 → 2 → 4` #### 4. 关键特性对比表 | 任务类型 | 常见API | 执行优先级 | 队列清空方式 | |----------|-------------------------|------------|------------------| | 微任务 | Promise.then, MutationObserver | 高 | 完全清空队列 | | 宏任务 | setTimeout, DOM事件 | 低 | 每次执行一个任务 | #### 5. 性能优化要点 - 避免长任务阻塞主线程(超过50ms的任务会导致界面卡顿) - 使用`requestIdleCallback`处理低优先级任务 - Web Workers处理CPU密集型任务[^1][^4] #### 6. 浏览器与Node.js差异 浏览器环境下每轮事件循环包含: 1. 执行一个宏任务 2. 清空微任务队列 3. 执行渲染操作 Node.js使用libuv库实现,包含6个阶段: 1. timers 2. pending callbacks 3. idle/prepare 4. poll 5. check 6. close callbacks[^3]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值