JavaScript相关(四)——事件循环

参考:
极客时间-消息队列和事件循环
js中的宏任务与微任务
javascript是单线程的原因是什么

JS是单线程语言,在浏览器执行渲染进程时,会遇到很多不同的事件类型,比如操作DOM节点、计算样式布局、执行JS任务、用户输入等,为了保证有序调度,不至于让某个事件堵塞,就需要一个系统算法来统筹调度这些任务,这就是事件循环系统。

每一个JS运行的线程环境中都有一个事件循环的任务队列,队列中的每一个任务被认为是宏任务、每个宏任务中又存在一个微任务的任务队列。在每一次的执行过程中,一般将事件分成同步事件和异步事件,遇到同步事件会先直接放主线程里执行,然后遇到异步事件会再分成宏任务、微任务放进任务队列里,每一次的宏任务执行完成,会再检查微任务队列中的任务,执行完毕后,本次循环结束,进行下一次循环,执行下一个宏任务。
这样既能保证实时性、又能保证一定的效率。

因此事件循环的机制大概步骤如下:

  1. 执行一个宏任务(栈中没有就从事件队列中获取)
  2. 执行过程中如果遇到微任务,就将它添加到微任务的任务队列中
  3. 宏任务执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行)
  4. 当前宏任务执行完毕,开始检查渲染,然后GUI线程接管渲染
  5. 渲染完毕后,JS线程继续接管,开始下一个宏任务(从事件队列中获取)
宏任务包含:
  • script(整体代码)
  • setTimeout
  • setInterval
  • I/O
  • UI交互事件
  • postMessage
  • MessageChannel
  • setImmediate(Node.js 环境)
微任务包含:
  • Promise.then
  • Object.observe
  • MutationObserver
  • process.nextTick(Node.js 环境)
Promise.resolve()
  .then(function() {
    console.log("promise0");
  })
  .then(function() {
    console.log("promise5");
  });
setTimeout(() => {
  console.log("timer1");
  Promise.resolve().then(function() {
    console.log("promise2");
  });
  Promise.resolve().then(function() {
    console.log("promise4");
  });
}, 0);
setTimeout(() => {
  console.log("timer2");
  Promise.resolve().then(function() {
    console.log("promise3");
  });
}, 0);
Promise.resolve().then(function() {
  console.log("promise1");
});
console.log("start");

// 说明,进入某个循环,执行解析,遇到微任务放当前的微任务队列【promise0,promise1】,宏任务放宏任务队列【timer1,timer2】
// OK没有异步任务了,遇到同步代码直接输出,start,然后查询任务队列,先清空当前循环中的微任务,输出promise0,这时又产生了一个微任务加入【promise1,promise5】
// 顺序输出promise1,promise5
// 微任务清空,查看宏任务列表,取出timer1,直接输出timer1,遇到一个微任务【promise2,promise4】执行输出,本次宏任务中没有微任务了,OK进下一个,timer2分析方式同1


// 打印结果: start promise0 promise1 promise5 timer1 promise2 promise4 timer2 promise3

题目分析

各种事件之间是如何相互通知的呢?比如把事件添加到哪个任务队列、任务执行完毕后异步通知

是通过消息队列来通知的

JS为什么是单线程

这主要和js的用途有关,js是作为浏览器的脚本语言,主要是实现用户与浏览器的交互,以及操作dom;这决定了它只能是单线程,否则会带来很复杂的同步问题。 举个例子:如果js被设计了多线程,如果有一个线程要修改一个dom元素,另一个线程要删除这个dom元素,此时浏览器就会一脸茫然,不知所措,如果要对使用的资源上锁的话可能又会加重操作开销。所以,为了避免复杂性,从一诞生,JavaScript就是单线程,这已经成了这门语言的核心特征,将来也不会改变。

  • 12
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值