事件循环中涉及到promise的执行顺序你真的了解吗
我们面试关于事件循环总能碰到各种刁钻的问题,但是只要掌握了其中的本质,一顿分析下来再刁钻的问题也会迎刃而解。下面就让我们来一起探索其中的原理吧~
首先,来看一段代码
new Promise(resolve => { console.log(1); resolve(3); }).then(num => { console.log(num) }); console.log(2) // 输出顺序为123 复制代码
下面我们就来分析上面这段代码的执行顺序:
第一步:new Promise(()=>{}).then(() => {})
其中.then
之前的代码是同步执行任务,所以会先打印出1。
第二步:resolve(3)
promise在resolve之后状态会从pengding
变为fulfilled
,之后Promise对象的then方法就会被调用,但是注意这里的方法是一个异步微任务。
第三步:console.log(2)
是同步任务。
所以,最终输出顺序为123。
如果在promise里面再加一个promise:
new Promise(resolve => { console.log(1); // resolve(3); Promise.resolve().then(()=> console.log(4)) }).then(num => { console.log(num) }); console.log(2) // 输出顺序为124 复制代码
没有resolve(),promise的状态一直是pending,并不会出发then()。
const promise = new Promise((resolve, reject) => { console.log(1) resolve() console.log(2) }) promise.then(() => { console.log(4) }) console.log(5) // 输出顺序为1254 复制代码
我们知道,JavaScript是基于事件驱动单线程执行的,所有任务都需要排队,也就是说前一个任务结束,才会去执行下一个任务。而像settimeout、ajax等异步操作的回调,会进入”任务队列“中,而且只有主线程中没有执行任何同步代码的前提下,才会执行异步回调。
Promise新建后立即执行,也就是说,Promise构造函数里的代码是同步执行的。
then方法指向的回调将在当前脚本所有同步任务执行完后执行。
其实,setTimeout有个最小执行时间(minimum delay of 4ms ),并不是0s执行的。
Macrotasks和Microtasks 都属于异步任务中的一种,常用api分类: macrotasks: setTimeout,setInterval,setImmediate, I/O, UI rendering microtasks:process.nextTick, Promise, MutationObserver
一个事件循环中只有一个macrotask任务,可以有一个或多个microtask任务。
其实还有很多知识点没有提到,后续会持续更新此文章~
作者:Lmuy
链接:https://juejin.cn/post/7023635161103204382