事件环

17 阅读4分钟

一、概念

1.进程:cpu正在进行的一个任务的运行过程的调度单位

    *在浏览器中 每个table都会开启一个【进程】
    *浏览器有一个主进程(用户界面)
    *每个tab各自有独立的渲染进程
    *每个进程包含了多个线程

2.线程

3.进程包含线程 线程在进程中运行

4.渲染引擎【☆】

   GUI渲染线程(渲染页面)
   JS引擎线程
   GUI渲染与JS引擎线程运行‘互相排斥’

5.渲染进程-GUI

  解析HTML、csss
  构建DOM、Render树
  初始布局与绘制
  重绘与回流
   

--事件

   事件触发线程:事件环Event loop
   事件线程:用户交互事件、setTimeout、Ajax

--宏任务微任务

   宏任务:【宿主(浏览器、node)】提供的异步方法和任务
           script、setTiomeout UI渲染
   微任务:【ES】提供的API运行
           Promise mutationsObserver
   

二、图解Event loop

image.png

  //eg1:
  Promise.resolve().then(() => {
        console.log('p1');
        setTimeout(() => {
            console.log('s2');
        }, 0)
    })

    setTimeout(() => {
        console.log('s1');
        Promise.resolve().then(() => {
            console.log('p2');
        })
    })

    /**
     * 执行栈:
     *      promise1.then cb ==> p1
     *      setTimeout1   cb ==> s1
     *      promise2.then cb ==> p2
     *      setTimeout2   cb ==> s2
     * 宏任务:          setTimeout1         x        setTimeout2        x
     *      回调队列    setTimeout1 cb      x        setTimeout2 cb     x
     * 
     * 微任务:          Promise1            x        promise2           x
     *      回调队列    Promise1.then cb    x        promise2.then cb   x
     * 
     * 
    */
    
    
    // eg1【扩展】
    Promise.resolve().then(() => {
        console.log('p1');
        setTimeout(() => {
            console.log('s2-1');
        }, 0)
        setTimeout(() => {
            console.log('s2-2');
        }, 0)
    })

    setTimeout(() => {
        console.log('s1');
        Promise.resolve().then(() => {
            console.log('p2-1');
        }).then(() => {
            console.log('p2-2');
        })
    })

    /**
     * JS执行栈
     *  promise1    cb ==> p1
     *  setTimeout1 cb ==> s1
     *  promise2    cb ==> p1-1
     *  promise3    cb ==> p2-2
     *  sto2        cb ==> s2-1
     *  sto3        cb ==> s2-2
     * 宏任务:     setTimeout1      x    sto2    x      sto3            x
     *   回调:     setTimeout1 cb   x    sto2 cb x     cto3 cb          x
     * 微任务:      promise1        x      promise2    x   promise3     x
     *   回调:      promise1   cb   x      promise2 cb x  promise3 cb   x
    */
    
    
    
    // eg2
    console.log(1);
    setTimeout(() => {
        console.log(2);
    }, 10)
    new Promise(function (resolve, reject) {
        console.log(3);
        resolve('')
        console.log(4);
    }).then(res => {
        console.log(5);
    })
    console.log(6);

    /**
     * JS执行栈
     *      1
     *      3
     *      4
     *      6
     * promise.then cb ==>5
     * setTimeout   cb ==>2
     * 异步宏任务  setTimeout       x
     *      回调  setTimeout cb     x
     * 异步微任务  Promise          x
     *      回调  promise.then cb   x
     * 
    */
    
    
    // eg2【扩展】❤坑❤==> 宏任务队列里面  拿取顺序要看setTimeout的执行时间 时间短的先拿 
    console.log(1);
    setTimeout(() => {
        Promise.resolve().then(() => {
            console.log(2);
        })
    }, 10)
    new Promise(function (resolve, reject) {
        console.log(3);
        resolve('')
        console.log(4);
    }).then(res => {
        setTimeout(() => {
            console.log(5);
        }, 0)
    })
    console.log(6);

    /**
     * JS执行栈
     *      1
     *      3
     *      4
     *      6
     * setTimeout cb ==> 5
     * promise2   cb ==> 2  
     * 宏任务 setTimeout1       setTimeout2     x
     *        setTimeout1 cb    setTimeout cb   x
     * 
     * 微任务 Promise1        x  promise2       
     *        Promise1 cb    x   promise2 cb   
    */
    
    
    

注意:

asnyc函数 会返回一个Promise实例 await函数 必须存在asnyc函数中

  // eg3
    let res = function () {
        console.log(1);
        return new Promise((resolve, reject) => {
            console.log(2);
            resolve(4)
        })
    }
    new Promise(async (resolve, reject) => {
        console.log(3);
        let test = await res()  //所以此时test是一个【微任务】  但是这个时候会调用test函数
        /**
         * await res() ===> res().then((test)=>{
         *  console.log(test);
         * })
        */
        console.log(test);
    })

    console.log(5);
    new Promise((resolve, reject) => {
        console.log(6);
    })
    console.log(7);

    /**
     * js执行栈
     *  res = function () {} //只赋值 不执行  此时 res是一个Promise实例
     * 
     *  3
     *  1
     *  2
     *  5
     *  6
     *  7
     *  4 //这个4是微任务 要等所用同步执行完成后才执行
     * 宏任务:
     * 
     * 微任务: awaitPromise        x
     *          awaitPromise cb     x
    */
    
    // eg3【超级扩展】
    let res = function () {
        console.log(1);
        return new Promise((resolve, reject) => {
            setTimeout(() => {  //s2
                new Promise((resolve) => {
                    console.log(2);
                    setTimeout(() => { //s5
                        console.log(3);
                    })
                })
            }, 0)
            resolve(5)
        })
    }
    new Promise(async (resolve, reject) => {
        setTimeout(() => {  //s1
            Promise.resolve().then(() => { //p2
                console.log(4);
            })
        }, 0)
        let test = await res()//awaitPromsie1  //所以此时test是一个【微任务】  但是这个时候会调用test函数
        /**
         * await res() ===> res().then((test)=>{
         *  console.log(test);
         * })
        */
        console.log(test);
    })
    setTimeout(() => {  //s3
        console.log(6);
    }, 0)
    new Promise((resolve, reject) => {
        setTimeout(() => { //s4
            console.log(7);
        }, 0)

    })
    console.log(8);

    /**
     * JS 执行栈
     * res = function () {} //不执行
     *  1
     *  8
     *  5
     *  4
     *  2
     *  6
     *  7
     *  3
     * 宏任务 setTimeout1    x   setTimeout2      x   setTimeout3     x    setTimeout4    7  s5
     *        setTimeout1 cb x   setTimeout2 cb   x   setTimeout3 cb  x    setTimeout4 cb 7  s5 cb
     * 微任务 awaitPromsie1      x  Promsie2      x   Promsie3  x
     *        awaitPromsie1 cb   x  Promsie2 cb   x   Promsie3  x
    */
    

交互事件(宏任务)

   //eg4
    const oBtn = document.getElementById('btn');
    oBtn.addEventListener('click', () => {
        console.log(1);
        Promise.resolve('m1').then((str) => {
            console.log(str);
        })
    }, false)

    oBtn.addEventListener('click', () => {
        console.log(2);
        Promise.resolve('m2').then((str) => {
            console.log(str);
        })
    }, false)
    oBtn.click()
    
    /**
     * 当我用js调用click() 函数的时候: //1 2 m1 m2
     *  同时执行m1 m2 两个宏任务】 并创建了两个微任务==>依次清空微任务
        当用户点击调用的时候:         //1 m1 2 m2
        按照上下顺序 先后监听 先执行m1宏任务 =>创建promise1微任务=>清除微任务
        先执行m2宏任务 =>创建promise2微任务=>清除微任务
    */
    

setInterval (在没遇到清除定clearInterval的时候 会一直执行setInterval)

    // eg5   在浏览器中,`setTimeout()`setInterval 的每调用一次定时器的最小间隔是 4ms ***
    console.log('start');
    const interval = setInterval(() => {
        console.log('setInterval');
    }, 0)

    setTimeout(() => { //s1
        console.log('settimeout 1');
        Promise.resolve()
            .then(() => { //p2
                console.log('promise 3');
            })
            .then(() => { //p3
                console.log('promise 4');
            })
            .then(() => { //p4
                setTimeout(() => {  //s2
                    console.log('settimeout 2');
                    Promise.resolve()
                        .then(() => { //p5
                            console.log('promsie 5');
                        })
                        .then(() => { //p6
                            console.log('promsie 6');
                        })
                        .then(() => { //p7
                            clearInterval(interval)
                        })
                }, 0)
            })
    }, 0)
    Promise.resolve()
        .then(() => {  //p1
            console.log('promsie 7');
        })



    /**
     * JS执行栈
     * start
     * p1 cb          ==> promsie 7
     * setInterval cb ==> setInterval
     * s1 cb          ==> settimeout 1
     * p2 cb          ==> promise 3
     * p3 cb          ==> promise 4
     * p4 cb          ==>
     * setInterval cb ==> setInterval
     * s2 cb          ==> settimeout 2
     * p5 cb          ==> promsie 5
     * p6 cb          ==> promsie 6
     * p7             ==> 清除定时器 不打印
     * 宏任务
     *      setInterval         x
     *          setInterval cb  x
     *      s1                  x
     *          s1 cb           x
     *      setInterval         x
     *          setInterval cb  x
     *      s2                  x
     *          s2 cb           x
     *      setInterval         x 清除定时器 不打印
     *          setInterval cb  x 清除定时器 不打印
     * 微任务
     *      p1          x
     *          p1 cb   x
     *      p2          x
     *          p2 cb   x
     *      p3          x
     *          p3 cb   x
     *      p4          x
     *          p4 cb   x
     *      p5          x
     *          p5 cb   x
     *      p6          x
     *          p6 cb   x
     *      p7          x
     *          p7 cb   x
     *
     *
    */
   
    // eg6
    setTimeout(() => { //s1
        console.log('setTimeout1');
        setTimeout(() => {//s3
            console.log('setTimeout3');
        }, 1000)
        Promise.resolve().then(data => {//p4
            console.log('then3');
        })
    }, 1000)
    Promise.resolve().then(() => { //p1
        console.log('then1');
        console.log('then4');
        Promise.resolve().then(data11 => {//p3
            console.log('then6');
        })
    })
    Promise.resolve().then(() => { //p2
        console.log('then2');
        console.log('then5');
        setTimeout(() => {//s2
            console.log('setTimeout2');
        }, 1000)
    })
    console.log(2);

    /**
     * JS执行栈
     * 2
     * p1.then cb ==> then1
     *                then4
     * p2.then cb ==> then2
     *                then5
     * p3.then cb ==> then6
     * s1 cb      ==> setTimeout1
     * p4.chen cb ==> then3
     * s2 cb      ==> setTimeout2
     * s3 cb      ==> setTimeout3
     * 
     * 宏任务
     *      s1              x
     *          s1 cb       x
     *      s2              x
     *          s2 cb       x
     *      s3              x
     *          s3 cb       x
     * 微任务
     *      p1              x
     *          p1.then cb  x
     *      p2              x
     *          p2.then cb  x
     *      p3              x
     *          p3.then cb  x 
     *      p4              x
     *          p4.then cb  x
    */