关于Js中的事件循环,微任务,宏任务的记录
关于Js中的事件循环,微任务,宏任务的记录
function log(key, ms) {
return setTimeout(() => {
console.log(key);
}, ms);
}
(async function () {
await log(1, 300);
await log(2, 200);
})();
(async function () {
let a = log(3, 200);
let b = log(4, 300);
await a;
await b;
})();
输出结果

js的特性
JS是一门单线程语言,单线程就意味着,所有的任务需要排队,前一个任务结束,才会执行下一个任务。这样所导致的问题是:如果JS执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的觉。为了解决这个问题,JS中出现了同步和异步。他们的本质区别是:一条流水线上各个流程的执行顺序不同。
同步任务:即主线程上的任务,按照顺序由上⾄下依次执⾏,当前⼀个任务执⾏完毕后,才能执⾏下⼀个任务。
异步任务:不进⼊主线程,⽽是进⼊任务队列的任务,执行完毕之后会产生一个回调函数,并且通知主线程。当主线程上的任务执行完后,就会调取最早通知自己的回调函数,使其进入主线程中执行。
事件循环Event Loop
事件循环的执行机制
- 1.进入到script标签,就进入到了第一次事件循环.
- 2.遇到同步代码,立即执行
- 3.遇到宏任务,放入到宏任务队列里.
- 4.遇到微任务,放入到微任务队列里.
- 5.执行完所有同步代码
- 6.执行微任务代码
- 7.微任务代码执行完毕,本次队列清空
- 寻找下一个宏任务,重复步骤1
- 以此反复直到清空所以宏任务,这种不断重复的执行机制,就叫做事件循环
宏任务主要包括:包括整体代码script,setTimeout,setInterval、setImmediate。
微任务主要包括:原生Promise(有些实现的promise将then方法放到了宏任务中)、process.nextTick、Object.observe(已废弃)、 MutationObserver 记住就行了。
关于setTimeout延时函数的执行过程如下:
- 调用setTimeout时:当调用
setTimeout
函数时,JavaScript 引擎会创建一个定时器; - 等待阶段
- 等待时间过后:当计时器设定的时间过去后,浏览器会将对应的回调函数放入宏任务队列中,等待执行。
- 执行回调
关于开头代码执行结果为 3-2-1-4

更直观的看

可以更加直观的看到
async 返回一个Promise,await 会把后面的代码放到微队列中,
await
这里有一个机制, 就是 await
的等待, 不会阻塞外部函数的执行, 而 await
等待的 如果是一个 Promise
则 Promise
里面的代码还是同步执行, 如果不是 Promise
,就会使用 Promise.resolve
来进行封装, 这里的 async2
是一个 async
方法, 里面的 打印会同步执行, 而 await async2()
后面的代码 会放到微任务队列中的第一个位置,等待外部同步代码执行完毕以后再执行。
