异步 JavaScript 的实现方式:事件循环队列

本文参考 The Definitive JavaScript Handbook for your next developer interview 一文中的 “Asynchronous JavaScript” 部分。

JavaScript 是单线程编程语言。这意味着 JavaScript 引擎一次只能执行一段代码,导致的后果是,当 JavaScript 引擎遇到一段比较耗时的代码时,就会阻塞后续代码的执行。

那 JavaScript 这样实现异步的呢?这归功于 回调函数事件循环队列

当我们使用 setTimeoutaddEventlistener 等方法时,JavaScript 执行到此,会使用 Event Manager 将方法中的回调函数移动到回调队列(Callback Queue)中。

当前执行过程中,除回调函数之外的其他语句,直接添加到调用栈(Call Stack)中执行,然后从调用栈删除。

等到当前调用栈空了(也就是本次事件循环队列结束),就开始执行下一次事件循环队列了---- Event Loop 将回调队列中的回调函数都移动到调用栈中,在调用栈中执行后,从调用栈删除。

让我们分解以下代码的执行,以了解该过程是如何工作的:

const first = function () {
  console.log('First message');
}
const second = function () {
  console.log('Second message');
}
const third = function() {
  console.log('Third message');
}

first();
setTimeout(second, 0);
third();

// 打印结果:
// First message
// Third message
// Second message
复制代码
  1. 起初,控制台无任何内容输出,调用栈和回调队列都是空的。
  2. first() 添加到调用栈。
  3. console.log('First message') 添加到调用栈。
  4. console.log('First message') 执行,控制台打印“First message”。
  5. console.log('First message') 从调用栈删除。
  6. first() 从调用栈删除。
  7. setTimeout(second, 0) 添加到调用栈。
  8. setTimeout(second, 0) 执行,并由事件管理器处理。0ms 后,Event Manager 将 second() 移动到回调队列。
  9. setTimeout(second, 0) 调用完成,从调用栈删除。
  10. third() 添加到调用栈。
  11. console.log('First message') 添加到调用栈。
  12. console.log('Third message') 执行,控制台打印“Third message”。
  13. console.log('Third message') 从调用栈删除。
  14. third() 从调用栈删除。
  15. 现在调用栈空了,second() 函数在回调队列中等待调用。
  16. Event Loop 将 second() 从回调队列移动到调用栈中。
  17. console.log("Second message") 添加到调用栈。
  18. console.log('Second message') 执行,控制台打印“Second message”。
  19. console.log('Second message') 从调用栈删除。
  20. second() 从调用栈删除。

需要注意的是:setTimeout(second, 0) 并不表示 0ms 后立即执行 second 函数,而是说---- 0ms 后,将 second 函数用 Event Manager 移动到回调队列中,等待 Event Loop 将其移动到调用栈中执行。

(完)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值