js事件循环机制
juejin.cn/post/701629… 这个里面的题目讲解的很好
segmentfault.com/a/119000002… 这篇文章里面的概念讲的不错
1请描述事件循环机制
js是单线程的,调用栈中的同步任务执行完毕后,会去轮询堆中的任务,流程:
1执行同步任务,清空call stack
2执行当前的微任务
3尝试dom渲染
4触发事件循环机制
2什么是微任务,什么是宏任务,2者的区别,与dom渲染的关系
同步任务执行完毕后再渲染dom
微任务在dom渲染前执行,宏任务在dom渲染后执行
宏任务是浏览器定义的,常见的宏任务有:setTimeout ajax dom事件
微任务是es6中的 ,常见的微任务有promise async/await
示例:可以体验宏任务,微任务与dom渲染的关系
//#region
const demo = document.getElementById('demo')
const p1 = `<p>我是p1</p>`
const p2 = `<p>我是p2</p>`
const p3 = `<p>我是p3</p>`
demo.innerHTML += p1
demo.innerHTML += p2
demo.innerHTML += p3
console.log('length', demo.children.length)
alert('同步任务执行完毕')
setTimeout(() => {
alert('setTimeout 宏任务', demo.children.length)
})
Promise.resolve().then(() => {
alert('promise 微任务', demo.children.length)
})
//#endregion
题目一:promise 与同步任务
//#region
1.
Promise.resolve().then(() => {
console.log(1)
}).catch(() => {
console.log(2)
}).then(() => {
console.log(3)
})
// 1
// 3
2.
Promise.resolve().then(() => {
console.log(1) //1
throw new Error('fail')
}).catch(() => {
console.log(2) //2 catch捕获后又返回一个成功的promise
}).then(() => {
console.log(3) //3
})
// 1
// 2
// 3
3.
Promise.resolve().then(() => {
console.log(1)
throw new Error('fail')
}).catch(() => {
console.log(2)
}).catch(() => {
console.log(3) //catch 用于捕获错误,上一个catch并没有抛出错误,所以这里不会打印
})
// 1
// 2
//#endregion
题目二 同步任务与async/await
1.
async function fn() {
return 100
}
(async function() {
const a = fn();
console.log(a) //promise async定义的函数返回的是一个promise
const b = await fn() //await 后返回的是函数定义的结果
console.log(b) //100
})()
// promise函数
// 100
2.
(async function() {
console.log('start') //start
const a = await 100;
console.log('a', a) //100
const b = await Promise.resolve(200)
console.log('b', b) //200
const c = await Promise.reject(300)
console.log('c', c) //报错了
console.log('end')
})()
//start
//100
//200
//报错了 Uncaught (in promise) 300
综合题
题目1
console.log(1) // 同步
setTimeout(() => {
console.log(2) // 异步:宏任务 setTimeout1
Promise.resolve().then(() => { // 异步:微任务 then1
console.log(3)
})
});
console.log(4) // 同步
new Promise((resolve, reject) => {
console.log(5) // 同步
resolve()
}).then(() => { // 异步:微任务 then2
console.log(6)
setTimeout(() => {
console.log(7) // 异步:宏任务 setTimeout2
})
})
console.log(8) // 同步
// 第一轮
// 先执行同步任务
// 1
// 4
// 5
// 8
// 产生 宏任务 setTimeout1 微任务 then2
// 第二轮
// 开始执行微任务 then2 log:6 产生宏任务 setTimeout2
// 执行 宏任务 setTimeout1 log:2 后面会打印undefined? 产生微任务 then1
// 第三轮
// 执行微任务then1 log:3
// 执行宏任务setTimeout2 log:7
题目二
console.log('script start') //同步
async function async1() {
await async2()
console.log('async1 end')
}
async function async2() {
console.log('async2 end')
}
async1() //同步
setTimeout(function() {
console.log('setTimeout')
}, 0)
new Promise(resolve => {
console.log('Promise')
resolve()
})
.then(function() {
console.log('promise1')
})
.then(function() {
console.log('promise2')
})
console.log('script end') //同步
// 第一轮
// script start
// 调用async1() 先调用async log:async2 end fix 为啥没有紧接着打印async1 end
// Promise 注意:Promise是立即执行函数,属于同步;then,catch属于异步
// script end
// 第二轮
// async1 end
// promise1
// promise2
// undefined
// setTimeout
再去理解下await的并发执行吧
const fn1 = function() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('fn1')
resolve()
}, 1000)
})
}
const fn2 = function() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('fn2')
resolve()
})
}, 2000)
}
async function test() {
const start = Date.now();
const res1 = fn1();
const res2 = fn2();
await res1;
await res2;
const end = Date.now();
console.log(`耗时${end-start}`) //2000
}
test();