例子:这个就是像食堂打饭排队,一个窗口有一个阿姨,问窗前的同学打哪些菜,然后确定这个同学不需要这个窗口的别的菜了,就给下一位同学打菜(请不要自杠插队行为).
- 宏任务就是阿姨给排队同学打菜
- 微任务就是排到队伍的同学选择要打的菜
- 先排队再打菜,等前面的打完要的菜了,再为下一个打菜
- 在一个事件流程里面,先走宏任务,再走微任务,等这个流程中所有的微任务
//这是错误的代码,主要验证当前微任务不走完是否会继续走下一个宏任务
console.log("食堂开门了");
//行为函数
function waitList(num = 1) {
return new Promise(resolve => {
console.log("第" + (num) + "位同学开始打饭了");
//假设平均每个人立刻时间打饭,是很假的
setTimeout(() => {
console.log("第" + (num++) + "位同学打好饭了");
});
if (num < 10) {
resolve();
}
}).then(() => waitList(num))
}
//第一位同学是不需要等待的,早起的鸟儿有虫吃
waitList();
//为了更形象
setTimeout(() => {
console.log(1111111)
})
Promise.resolve().then(() => {
console.log(2222222)
})
//食堂开门了
//第1位同学开始打饭了
//第1位同学开始打饭了
//2222222
//第1位同学开始打饭了 * n
//这是我单身23年手速ctrl+c 弄出来的0.0
可以看出来,setTimeout的回调都没有执行,一直在走的都是then的回调,从第三个和第四个可以看出了,先走了上面的then,然后走了下面的then,然后就一直走第三个then之后的then的…(…像极了俄罗斯套娃)
也就是说以then为代表的微任务是有自己的队列的,自己这个队列走完之后才会走setTimeout为代表的宏任务的队列,因为不停地套娃,像极了一个数组shift之后又push,然后length一直不为0,就一直死磕这个数组
总结:主线程可以看做是一个宏任务,宏任务完成之后,检查微任务队列,并执行可执行的队列,执行队列完成之后,检查宏任务队列,再检查微任务队列,进行事件循环
//这是正常的一个逻辑流程,一个人打完,下一个
//主要还是上面的错误代码验证事件循环的问题
console.log("食堂开门了");
//行为函数
function waitList(num = 1){
return new Promise(resolve=>{
console.log("第" + (num) + "位同学开始打饭了");
//假设平均每个人需要3秒时间打饭,是很假的
setTimeout(() => {
console.log("第" + (num++) + "位同学打好饭了");
if(num<10){
resolve(num);
}
}, 3000);
}).then(num=>waitList(num))
}
//第一位同学是不需要等待的,早起的鸟儿有虫吃
waitList();
I/O 输入输出流—cin/cout之后,我对输入输出已经产生很大的误解了…
setTimeout/setInterval --定时器
setImmediate --nodejs 立即执行函数
requestAnimationFrame --浏览器,动画函数
process.nextTick --nodejs 进程的下一刻,这是个大哥,最先执行的微任务系列
MutationObserver – 浏览器节点观察者
Promise.then catch finally — es6 Promise语法
//基础面试题
setTimeout(_ => console.log(1))
new Promise(resolve => {
resolve()
console.log(2)
}).then(_ => {
console.log(3)
})
console.log(4)
解析:
- 遇到setTimeout ,注册回调函数到宏任务队列
- 执行完成Promise参数,将then回调注册到微任务队列
- 执行console.log(4)
- 主线程完成,检查微任务队列 执行console.log(3),当前微任务队列清空
- 开始下一轮宏任务 执行console.log(1),宏任务完成
疑问:
都没有之后.事件循环是否还是一直存在,还是两者都空了之后就停止了?结果:
2
4
3
1
这篇文章断断续续写了3天,写到后来自己都写懵了…