JS 的事件循环

前言

本文主要是关于JS 事件循环的简单理解

一、线程和进程

首先我们需要了解什么是进程和线程

1.1 进程

计算机中的程序关于某数据集合上的一次运行活动, 是系统进行资源分配和调度的基本单位,是操作系统结构的基础。 相当于运行中的程序的描述,一个运行的程序就对应着一个进程。 单核 CPU 再同一时间内有且只有一个进程再运行。

1.2 线程

是操作系统能够进行运算调度的最小单位。它被包含在进程中,是进程中的一个执行路径,一个进程可以包含多个线程。线程可以共享所在进程的地址空间和其他资源。

二、JS 是单线程

2.1 原因

JS 负责处理页面中用户的交互,以及操作 DOM 树、CSS 样式树。这决定了它只能是单线程,如果 JS 是多线程来操作 DOM,则可能出现冲突。 比如 JS 两个线程同时操作一个 DOM,一个线程需要浏删除DOM节点,而另一个线程却需要修改这个节点,这个时候浏览器就无法决定采用哪一种策略了
而单线程就意味着所有任务要按顺序完成。这样 JS 就不会显得慢吗?为了避免 IO 设备(比如:上传,读取文件,下载等)过慢,JS 不管 IO 设备,先运行排在后面的任务,等 IO 设备返回了结果,再执行下去。这样,就有了两个任务,一个是同步任务,另一个是异步任务。

三、同步任务与异步任务

3.1 同步任务

指在主线程排队执行的任务,前一个任务执行完毕后,才能执行后一个任务,执行的顺序和任务的排列顺序是一致的。
示例:

console.log('begin') ;
function bar () { 
console.log('1') ;
} 
function foo () { 
console.log('2') ;
bar();
 } 
foo() ;
console.log('end');

输出的顺序为: begin 2 1 end

3.2 异步任务

异步任务会被主线程挂起,不会进入主线程,而是进入任务队列,只有队列通知主线程某个异步任务可以执行,并且执行栈为空时,对应的任务才会进入执行栈获得执行的机会。
示例:

console.log('begin') ;
setTimeout(function timer1 () {
  console.log('1')
}, 1800)
setTimeout(function timer2 () {
  console.log('2')
  setTimeout(function inner () {
    console.log('3')
  }, 1000)
}, 1000)
console.log('end');

输出的顺序为:begin end 2 1 3

3.3 异步任务的运行方式

主线程会先运行所有的同步任务,在碰到需要异步执行的任务时,会将异步任务挂起,异步任务准备完毕后会进入浏览器的任务队列里。任务队列是一个先进先出的数据结构,排在前面的事件,优先被主线程读取。当同步任务处理完,主线程就根据服务器的处理先后顺序执行剩余的异步任务。
以上面示例为准,在运行到 setTimeout 这类定时任务时,会将它们放在一边,主线程继续向下执行,所以第二个为 end 。当定时时刻达到时,它们按先后顺序放入任务队列中等待主线程执行。当主线程空闲时,它们按先入先出的顺序来执行。所以分别输出 2 1 3。

如下图:

3.4 js 中常见的异步执行代码

1.ajax请求
2.定时器
3.事件处理函数:
(1)延迟类:setTimeout、setInterval、requestAnimationFrame、setImmediate。
(2)监听事件实现的类型:监听 new Image 加载状态、监听 script 加载状态、监听 iframe 加载状态、Message。
(3)带有异步功能类型 Promise、ajax等等。

四、事件循环

我们可以发现,上图中事件队列与最后的执行是双向的,表示当主线程内的任务执行完毕时,会循环不断地从任务队列中读取事件,在主线程中执行,这里就是我们常说的事件循环了。

五、宏任务和微任务

在异步任务被挂起时,会分为两种任务队列,分别为宏任务队列和微任务队列。

5.1 常见的宏任务
  • setTimeout
  • setInterval
  • I/O
  • script 代码…
5.2 常见的微任务
  • callback
  • Object.observe
  • Promise的回调
  • process.nextTick …
5.3 执行顺序

首先执行主线程中的宏任务,碰到宏任务放入宏任务队列,碰到微任务放入微任务队列。主线程执行完毕后,执行任务队列里的微任务,然后执行下一个宏任务,顺序如上。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值