这是我参与【第四届青训营】笔记创作活动的第4天
1.什么是同步任务与异步任务
同步任务
- 同步任务又叫做非耗时任务,指的是在主线程上排队执行的那些任务
- 只有前一个任务执行完毕,才能执行后一个任务
异步任务
- 异步任务又叫做耗时任务,异步任务由js委托给宿主环境进行执行
- 宿主环境:即js的执行环境,js在浏览器里执行的,宿主环境就是浏览器,在nodejs里执行的,宿主环境就是node
- 当异步任务执行完成后,会通知js主线程执行异步任务的回调函数
2.同步任务和异步任务的执行过程
- 同步任务有js主线程次序执行
- 异步任务委托给宿主环境执行
- 已完成的异步任务对应的回调函数,会被加入到任务队列中的回调函数,次序执行
- js主线程的执行栈被清空后,会读取任务队列中的回调函数,次序执行
- js主线程不断重复第(4)步 即EventLoop的工作
代码案例
// 同步任务
console.log('A');
// 异步任务
setTimeout(() => {
console.log('B');
}, 10);
// 异步任务
setTimeout(() => {
console.log('C');
}, 0);
// 同步任务
console.log('D');
// 结果:A D C B
在上面的代码中,js主线程遇到同步任务A则立即打印;遇到异步任务B,则交由宿主环境开始计时;与此同时,主线程也执行到异步任务C,则继续交由宿主环境开始计时,计时0ms计时完毕,则把回调函数() => {console.log('C');}放入任务队列中;再接着js主线程执行同步任务D;紧接着异步任务B计时结束后,回调函数也进入任务队列。然后因为主线程执行栈已经清空了,接下来从任务队列里取出任务并且执行。因此最终结果是ADCB
宏任务与微任务
什么是宏任务与微任务
异步任务又分为宏任务和微任务,任务执行的先后次序与这个任务是宏任务还是微任务有关
常见的宏任务与微任务
宏任务
- 异步ajax请求
- setTimeout setInterval
- 文件操作
微任务
- Promise.then .catch .finally
- process.nextTick
执行机制
- 按序完成同步任务,分好微任务队列,宏任务队列
- 同步任务完成后,再查看微任务队列,清空微任务队列后,执行第一个宏任务
- 第一个宏任务开始执行 重复(1)
- 第一个宏任务里的同步任务清空后,再清空微任务,继续执行第二个任务
- 重复(3)(4)
代码案例
// 同步任务1
console.log(1);
// 异步任务2
setTimeout(() => {
console.log(2);
new Promise(function (res) {
console.log(3);
res();
}).then(function () {
console.log(4);
})
setTimeout(() => {
console.log(5);
}, 0);
}, 0);
// 同步任务3,异步任务4
new Promise(function (res) {
console.log(6);
res();
}).then(function () {
console.log(7);
})
// 同步任务5
console.log(8);
// 结果: 1 6 8 7 2 3 4 5
在上面的代码中,js主线程遇到同步任务1则立即打印1;遇到异步任务2,则交由宿主环境开始计时,计时完交由宏任务队列;主线程继续遇到同步任务3(注意:Promise接收的函数为当前执行栈的,即为同步任务),打印6;然后异步任务4计时完后又交由微任务队列;遇到同步任务5,打印8;此时,宏任务队列有异步任务2,微任务队列有异步任务4,微任务队列未清空,需先执行微任务队列里的回调函数,即打印7;打印7完,微任务队列已清空,开始执行第一个宏任务;打印完2和3后,微任务队列和宏任务队列有新增了两个回调函数;此时微任务队列又未被清空,则先执行微任务队列,即打印4;微任务队列为空,执行第二个宏任务。即打印5;
因此最终结果为1 6 8 7 2 3 4 5