本文知识点:
- 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执行
- 然后继续轮询查找(永动机一样)
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渲染
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
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END