- 什么是event loop?
事件循环(event loop)就是 任务在主线程不断进栈出栈的一个循环过程。任务会在将要执行时进入主线程,在执行完毕后会退出主线程。
- 为什么会有event loop?它解决了什么问题?
我们知道JavaScript 语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。为了协调事件、用户交互、脚本、UI 渲染和网络处理等行为,防止主线程的不阻塞,Event Loop 的方案应运而生。为了解决这个问题,js出现了同步和异步两种任务,两种任务的差异就在于执行的优先级不同。event loop就是对任务的执行顺序做了详细的规范。
- 同步任务和异步任务
js中的任务主要分为同步任务和异步任务。
同步任务又叫做非耗时任务,指的是在主线程上排队执行的那些任务。只有前一个任务执行完毕,才能执行后一个任务。
异步任务又叫做耗时任务,异步任务由JavaScript 委托给宿主环境进行执行。当异步任务执行完成后,会通知JavaScript 主线程执行异步任务的回调函数。
- 宏任务和微任务
js中的异步任务分为宏任务和微任务。
常见的微任务有:Promise.then(),.then中的逻辑是微任务;process.nextTick(node环境)。
常见的宏任务有:setTimeout、setInterval、setImmediate(node环境)、xhr(发送网络请求),callback。
-
任务的执行顺序
1.把同步任务相继加入同步任务队列。
2.把同步任务队列的任务相继加入主线程。
3.待主线程的任务相继执行完毕后,把主线程队列清空。
4.把微任务相继加入微任务队列。
5.把微任务队列的任务相继加入主线程。
6.待主线程的任务相继执行完毕后,把主线程队列清空。
7.把宏任务相继加入宏任务队列。注意:当碰到计时器时,不会立即把计时器里的任务加入宏任务队列,计时器会开始运行,等待计时器运行完成才会把计时器里面的任务加入宏任务队列。
8.把宏任务队列的任务相继加入主线程。
9.待主线程的任务相继执行完毕后,把主线程队列清空。
-
举个例子
setTimeout(function() {console.log('1');},0) //宏任务
new Promise(function(resolve) { console.log('2'); //同步任务 resolve()}).then(function() { console.log('3'); //微任务})
console.log('4'); //同步任务
结果就很明显了,运行顺序是4 2 3 1
- 进阶
console.log(1)
setTimeout(function() { console.log(2) new Promise(function(resolve) { console.log(3) resolve() }).then(function() { console.log(4) })},3000)
new Promise(function(resolve) { console.log(5) resolve()}).then(function() { console.log(6)})
setTimeout(function() { console.log(7) new Promise(function(resolve) { console.log(8) resolve() }).then(function() { console.log(9) })},2000)
console.log(10)
setTimeout(function() { console.log(11) new Promise(function(resolve) { console.log(12) resolve() }).then(function() { console.log(13) })},0)
// 1 5 10 6 11 12 13 7 8 9 2 3 4
你答对了吗?
-
结语
祝看这篇文章的小伙伴们技术越来越好。