js事件循环机制

276 阅读3分钟

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();