原理简述
1 所有的同步任务都在主线程上执行,这形成了一个执行栈
2 主线程之外还存在一个消息队列,只要异步任务执行完成就会到消息队列中排队
3 一旦执行栈中所有的同步任务执行完成,系统就会按先入先出,先微任务后宏任务的规则读取消息队列中的任务(消息)并放到主线程上执行
4 主线程不断执行第三步的过程就是 事件循环
注: 主线程不断重复读取消息(消息队列中的任务) 执行消息的过程就是事件循环
单线程
JavaScript是单线程的语言,也就是同一时间内是能做一件事,而这个单线程的特性与它的用途有关,作为浏览器的脚本语言,js的主要用途是与用户交互,以及操作dom,这决定了它只能是单线程,否则就会带来非常复杂的同步问题
排队
单线程就意味着所有任务都需要排队,前一个任务结束才会执行下一个任务.如果前一个任务耗时很长就不得一直等待着,等待的时候不能进行任何其他的操作
同步
如果在函数返回的时候,调用者就能直接得到预期的结果(即拿到预期的返回值或看到了预期的结果),那么这个函数就是同步的. 一个js中的判断,循环,页面的加载就是典型的同步任务
异步
函数在返回的时候调用者不能直接得到预期的结果,而是需要使用通过一定的方法(如注入回调函数)才能得到预期的结果,那么这个函数就是异步的. 定时器,ajax,promise函数就是典型的异步任务
消息队列
消息队列也称任务队列或事件队列,总之是和异步任务相关的队列
这个队列和排队是类似的,是一中先入先出的形式,只要异步任务执行完成,就可以到消息队列中排队
在消息队列中的任务存在微任务和宏任务之分,在两者都有的情况下优先执行微任务(即使宏任务先进入排队,也是先执行微任务)
这样当主线程上空闲的时候就可以从消息队列中获取任务并执行
消息队列中的任务就是注册异步任务添加的回调函数
注: 在消息队列中排队的不用异步任务而是异步任务执行完成之后需要触发的回调函数(异步任务的执行存在于异步的执行栈中,同一时间内是可以多个异步任务在执行的)
微任务
消息队列中的一种任务类型
优先级 process.nextTick > Promise > MutationObserver
在微任务执行的过程中如果触发了新的微任务会立即排队
每次只有把所有的微任务执行完成才会执行宏任务
宏任务
消息队列中的一种任务类型
优先级 主代码块(script中的代码) > setImmediate > MessageChannel > setTimeout / setInterval
在消息队列中预先执行微任务,微任务全部执行完成才会执行宏任务,每执行完一个宏任务就会查考消息队列中是否存在新的微任务,如果有则优先执行微任务.其中存在一个循环