EventLoop
1.JavaScript是单线程语言
JavaScript是一门单线程执行的编程语言,也就是同一个时间只能做一件事情。
问题:前一个任务非常耗时,后续的任务就不得不一直等待,导致程序假死的问题
2:同步任务和异步任务
为了防止某个耗时任务导致程序假死的问题,JavaScript 把待执行的任务分为了两类:
① 同步任务(synchronous)
-
又叫做非耗时任务,指的是在主线程上排队执行的那些任务
-
只有前一个任务执行完毕,才能执行后一个任务
② 异步任务(asynchronous)
- 又叫做耗时任务,异步任务由 JavaScript 委托给宿主环境进行执行
- 当异步任务执行完成后,会通知 JavaScript 主线程执行异步任务的回调函数
同步任务和异步任务执行过程
①同步任务由JavaScript 主线程按次序执行
②异步任务委托给宿主环境执行
③已完成的异步任务对应的回调函数,会被加入到任务队列中等待执行
④JavaScript 主线程的执行栈被清空后,会读取任务队列中的回调函数,次序执行
⑤JavaScript 主线程不断重复上面的4 步
事件循环EventLoop
JavaScript 主线程从"任务队列"中读取异步任务的回调函数,放到执行栈中依次执行,这个过程是循环不断的,所以整个的这种运行机制称为事件循环EventLoop
import thenFs from 'then-fs'
console.log("A");
thenFs.readFile('./files/1.txt', 'utf8').then(data => {
console.log("B");
})
setTimeout(() => {
console.log("C");
}, 0)
console.log("D");
结果:A D C B’
A和D属于同步任务,根据代码的先后顺序依次执行
C和B是异步任务,它们的回调函数会被加入到任务队列中,等待主线程空闲时再执行
宏任务和微任务
1什么是宏任务和微任务
JavaScript把异步任务又做了进一步的划分,异步任务又分为两类:
①宏任务
- 异步ajax请求
- setTimeout,setInterval
- 文件操作
②微任务
- Promise.then,.catch,.finally
- process.nextTick
执行顺序
先执行所有同步
所有同步执行完之后会检查是否存在待执行的微任务,如果有,则执行完所有微任务之后,再执行宏任务
每一个宏任务执行完之后,也会检查是否存在待执行的微任务,同样执行完所有微任务之后,再继续执行下一个宏任务
可以理解为每一次执行宏任务之前,都要检查执行微任务。
1:小张和小王去银行办业务,首先,需要取号之后进行排队
宏任务队列
2:假设当前银行网点只有一个柜员,小张办理存款业务,小王只能等待
单线程 宏任务按次序执行
3:小张办完存款业务后,柜员询问他是否还想办理其他业务?
当前宏任务执行完,检查是否有微任务
4:小张告诉柜员,想要买理财产品,再办个信用卡,最后兑换点纪念币
执行微任务,后续宏任务被推迟
5:小张离开柜台后,柜员开始为小王办理业务
所有微任务执行完毕,开始执行下一个宏任务
案例
setTimeout(function () {
console.log(1)
}, 70)
new Promise(function (resolve) {
console.log(2)
//ajax请求
resolve()
}).then(function () {
console.log(3)
})
console.log(4)
结果:2 4 3 1
1:先执行所有的同步任务 输出2 输出4
2:再执行微任务 输出3
3: 再执行下一个宏任务 输出1
ole.log(3)
})
console.log(4)
结果:2 4 3 1
1:先执行所有的同步任务 输出2 输出4
2:再执行微任务 输出3
3: 再执行下一个宏任务 输出1
可以试试看,下面的代码运行结果:
```js
setTimeout(function () {
console.log(1)
}, 0)
new Promise(function (resolve) {
console.log(2)
resolve()
}).then(function () {
console.log(3)
})
setTimeout(function () {
console.log(6)
},0)
console.log(4)
//24316
console.log(1);
setTimeout(function () {
console.log(2)
new Promise(function (resolve) {
console.log(3)
resolve()
}).then(function () {
console.log(4)
})
})
new Promise(function (resolve) {
console.log(5)
resolve()
})
.then(function () {
console.log(6)
})
setTimeout(() => {
new Promise(function (resolve) {
console.log(8)
resolve()
}).then(function () {
console.log(9)
})
console.log(7)
});
console.log(10);
1 5 10 6 2 3 4 7 8 9
留下一片深入文章:JavaScript 运行机制详解:再谈Event Loop