8-异步进阶

本文知识点:

  • event loop
  • promise 进阶
  • async/await
  • 微任务/宏任务
  • 场景题-promise then和catch的连接
  • 场景题-async/await语法
  • 场景题- promise和setTimeout的顺序
  • 场景题-外加async/await的顺序问题

问答题

1 请描述event loop(事件循环/事件轮询)的机制,可画图
2 什么是宏任务和微任务,两者有什么区别?
3 Promise有哪三种状态?如何变化?
复制代码
  • 请描述event loop(事件循环/事件轮询)的机制,可画图
  • 什么是宏任务和微任务,两者有什么区别?
  • Promise有哪三种状态?如何变化?
  • 场景题-promise then和catch的连接
//第一题
Promise.resolve().then(()=>{
    console.log(1);
}).catch(()=>{
    console.log(2);
}).then(()=>{
    console.log(3);
})

//第二题
Promise.resolve().then(()=>{
    console.log(1);
    throw new Error('error1')
}).catch(()=>{
    console.log(2);
}).then(()=>{
    console.log(3);
})

//第三题
Promise.resolve().then(()=>{
    console.log(1);
    throw new Error('error1')
}).catch(()=>{
    console.log(2);
}).catch(()=>{
    console.log(3);
})
复制代码
  • 场景题-async/await语法
async function fn(){
    return 100;
}
(async function(){
    const a = fn();//?? 返回一个promise 值是100
    const b = await fn(); //?? 返回值100(await 相当于promise的then)
})()

(async function(){
    console.log('start');
    const a = await 100;
    console.log('a',a);
    const b = await Promise.resolve(200);
    console.log('b',b);
    const c = await Promise.resolve(300);
    console.log('c',c);
    console.log('end');
    
})() //执行完毕,打印出哪些内容? 
//只打印 start  a:100 b:200
复制代码
  • 场景题- promise和setTimeout的顺序
console.log(100)
setTimeout(()=>{
    console.log(200)
})
Promise.resolve().then(()=>{
    console.log(300)
})
console.log(400)

//100 400 300 200
复制代码
  • 场景题-外加async/await的顺序问题
async function async1(){
    console.log('async1 start'); //2
    await async2();
    // await后面都作为回调内容 -- 微任务
    console.log('async1 end') //6   
}
async function async2(){
    console.log('async2') //3
}
console.log('script start') //1

setTimeout(function(){ //宏任务 
    console.log('setTimeout') //8
},0)

async1();

//**** 初始化promise时,传入的回调函数会立刻被执行
new Promise(function(resolve){
    console.log('promise1') //4
    resolve()
}).then(function(){ //微任务
    console.log('promise2') //7
})

console.log('script end')//5
复制代码

event loop(事件循环/事件轮询)

  • JS是单线程运行的

  • 异步要基于回调来实现

  • event loop就是异步回调的实现原理

  • 回顾:JS如何执行?

    • 从前到后,一行一行执行
    • 如果某一行执行报错,则停止下面代码的执行
    • 先把同步代码执行完,再执行异步

示例

console.log('Hi')
setTimeout(function cb(){
    console.log('cb1')
},5000)
console.log('Bye')
复制代码

event loop过程

  • 同步代码,一行一行放在Call Stack执行
  • 遇到异步,会先“记录”下,等待时机(定时、网络请求等)
  • 时机到了,就移动到Callback Queue
  • 如Call Stack为空(即同步代码执行完)Event Loop开始工作
  • 轮询查找Callback Queue,如有则移动到Call Stack执行
  • 然后继续轮询查找(永动机一样)

image.png

DOM事件和event loop

  • JS是单线程的
  • 异步(setTimeout,ajax等)使用回调,基于event loop
  • DOM事件也使用回调,基于event loop
console.log('Hi')
setTimeout(function cb(){
    console.log('cb1')
},5000)
console.log('Bye')
复制代码
<button id="btn1">提交</button>
<script>
console.log('Hi')
$('#btn1').click(function(e){
    console.log('button clicked')
})
console.log('Bye')
</script>
复制代码

宏任务macroTask和微任务micro Task

  • 什么是宏任务,什么是微任务
  • event loop和DOM渲染
  • 微任务和宏任务的区别

代码演示

console.log(100)
setTimeout(()=>{
    console.log(200)
})
Promise.resolve().then(()=>{
    console.log(300)
})
console.log(400)
//答案 100 400 300 200 
复制代码

宏任务和微任务

  • 宏任务:setTimeout,setInterval,Ajax,DOM事件
  • 微任务:Promise async/await
  • 微任务执行时机比宏任务要早

event loop和DOM渲染

image.png

const $p1 = $('<p>一段文字</p>');
const $p2 = $('<p>一段文字</p>');
const $p3 = $('<p>一段文字</p>');
$('#container')
    .append($p1)
    .append($p2)
    .append($p3)
console.log('length',$('#container').children().length) //3
alert('本次 call stack结束,DOM结构已更新,但尚未触发渲染')
//(alert会阻断js执行,也会阻断DOM渲染,便于查看效果)
复制代码
const $p1 = $('<p>一段文字</p>');
const $p2 = $('<p>一段文字</p>');
const $p3 = $('<p>一段文字</p>');
$('#container')
    .append($p1)
    .append($p2)
    .append($p3)
    
//微任务:DOM渲染前触发
Promise.resolve().then(()=>{
    console.log('length1',
        $('#container').children().length)//3
        alert('Promise then')//DOM 渲染了吗?---//NO
})

//宏任务:DOM渲染后触发
setTimeout(()=>{
    console.log('length2',
        $('#container').children().length)//3
        alert('setTimeout') //DOM渲染了吗? ---YES
})
复制代码

从event loop解释,为何微任务比宏任务更早,会在渲染前触发

  • 宏任务是由浏览器规定的:setTimeout,setInterval,Ajax,DOM事件
  • 微任务是ES6语法规定的:Promise async/await

image.png

image.png

image.png

image.png

image.png

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享