事件循环、任务与微任务的关系

事件循环(Event Loop)
javascript是一门单线程语言,单线程意味着会依次执行任务,当遇到耗时任务时,则会等待结果。
于是,javascript的设计者想到将那些耗时任务挂起,主线程继续执行。所以将任务分为同步任务与异步任务。
(1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
(4)主线程不断重复上面的第三步
完整的事件循环(Event Loop)
 1)检查(宏)任务(task)队列 取先入队的宏任务,在执行栈中执行 
 2)宏任务结束,检查微任务(micro task)队列,若存在微任务,将微任务加入到执行栈执行,直至清空微任务 
 3)渲染页面(如果需要的话)
 4) 检查(宏)任务(task)队列,如果存在,重复上面三步,进入下一个事件循环;
 若无,则等待;主线程会定时去检查。

宏任务:1. script
2. setTimeout/setInterval
3. UI rendering/UI事件
4. postMessage,MessageChannel
5. setImmediate,I/O(Node.js)

微任务:1. .then() (即async/await相当于期约在函数中的的应用)
6. MutaionObserver
7. Object.observe(已废弃;Proxy 对象替代)
8. process.nextTick(Node.js)

搞懂下面三题 就稳了

console.log(111);
let p1 = new Promise(resolve => {
  setTimeout(() => {
    console.log(222);
    resolve();  // 注意resolve位置的区别
    Promise.resolve().then(() => {
      console.log(333);
    });
  }, 0);
});
p1.then(() => {
  new Promise(resolve => {
    console.log(444);
    resolve();
  }).then(()=>console.log(555))
}).then(()=>console.log(666))
console.log(777)
111->777->222->444->333->555->666
<script></script>是宏任务
1)先同步执行console.log(111);
2)遇到setTimeout,交给浏览器做计时,当满足条件时,会将其推入宏任务队列;
3)遇到p1,Promise状态未定,浏览器等待执行;
4)执行console.log(777);
5)检查微任务队列,无微任务,检查宏任务队列,执行下一个宏任务(task) setTimeout
6)执行console.log(222);
7)resolve();p1状态落定,执行.then(),处理程序prom1推入微任务队列;
8)接着遇到一个解决的期约,无需等待,直接执行.then(),将处理程序prom2推入任务队列;
9)宏任务执行完毕,检查微任务队列,执行prom1,console.log(444);
10)返回一个被Promise.resolve()包装的undefined。依次触发两个.then() Prom3 Prom4进入微任务队列;prom1执行完毕
11)prom2进入主执行栈执行 console.log(333);完毕
12)prom3、prom4依次进入主执行栈执行console.log(555);console.log(666);
console.log(111);
let p1 = new Promise(resolve => {
  setTimeout(() => {
    console.log(222);
    Promise.resolve().then(() => {
      console.log(333);
    });
    resolve(); // 注意resolve位置的区别
  }, 0);
});
p1.then(() => {
  new Promise(resolve => {
    console.log(444);
    resolve();
  }).then(()=>console.log(555))
}).then(()=>console.log(666))
console.log(777)
111->777->222->333->444->555->666
async function async1() {        
  console.log('async1 start');
  await async2();
  console.log('async1 end');
}
async function async2() {
  Promise.resolve().then(() => console.log(2222));
  setTimeout(console.log,0,'async2'); 
}

console.log('script start'); 
setTimeout(function() {
    console.log('setTimeout');
}, 0);  
async1();
// setTimeout(console.log,0,'1111')
new Promise(function(resolve) {
    console.log('promise1');
    resolve();
  }).then(function() {
    console.log('promise2');
});
console.log('script end');
script start->async1 start->promise1->script end->222->async1 end->promise2->setTimeout->async2

const myPromise = Promise.resolve(Promise.resolve('666!'));

function funcOne() {
    myPromise.then(res => res).then(res => console.log(res));
    console.log('111');
}

async function funcTwo() {
    console.log('222');
    const res = await myPromise;
    console.log('444');
    console.log(await res);
    console.log('777');
}
async function funcThree() {
    console.log(await myPromise.then(()=> console.log('555')).then(()=>console.log('888')));
}
funcOne();
funcTwo();
funcThree();
console.log('333');
111 --> 222-->333-> 444-->555-->666!-->666!-->777-->888
async function async1() {
    await async2()
    console.log('2')
}
function async2() {
    console.log('3')
    return Promise.resolve().then(()=>{
      console.log('4')
    });
}

async1()

new Promise(resolve => {
    console.log('6')
    resolve()
})
.then(function() {
    console.log('7')
})
.then(function() {
    console.log('8')
})
.then(function() {
    console.log('9')
})
3  6  4  7  2  8  9

注意: 和上面的区别 有 return 和 没有return

async function async1() {
    await async2()
    console.log('2')
}
function async2() {
    console.log('3')
    Promise.resolve().then(()=>{
      console.log('4')
    });
}

async1()

new Promise(resolve => {
    console.log('6')
    resolve()
})
.then(function() {
    console.log('7')
})
.then(function() {
    console.log('8')
})
.then(function() {
    console.log('9')
})
3  6  4  2  7  8  9

尽量不要在 async 标识的函数内部返回 Promise ,会导致运行时机的变化(目前还不知道 如何解释)

async function async1() {
  return Promise.resolve(2)
}
async1().then(()=>{
  console.log(1)
})

new Promise(resolve => {
    console.log('6')
    resolve()
})
.then(function() {
    console.log('7')
})
.then(function() {
    console.log('8')
})
.then(function() {
    console.log('9')
})
.then(function() {
    console.log('10')
})
6  7  8  1  9  10
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值