zoukankan      html  css  js  c++  java
  • EventLoop事件轮询 宏任务和微任务

    EventLoop事件轮询 宏任务和微任务

    浏览器从服务器获取到代码后,浏览器会开辟一个GUI渲染线程,GUI从上到下开始执行代码。
    浏览器是多线程的,包含GUI渲染线程、HTTP网络请求线程(并发数6-7)、事件监听定时器监听。但JS代码的运行是单线程的。

    执行过程:执行完宏任务 => 执行微任务 => 页面重新渲染 => 再执行新一轮宏任务

    将所有的任务分为2种,一种是同步任务,一种是异步任务。

    • 同步任务:在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行下一个任务。同步任务是在调用栈call stack中执行。

    • 异步任务: 不进入主线程,进入“任务队列”task queue 的任务,只要异步任务有了运行结果,就会在task queue中放置一个事件。 只有任务队列通知主线程,异步任务可以执行了,该任务才会进入主线程。

    • 任务队列: 是一个事件队列(也可以了解为消息队列)。一旦一个异步任务完成,就在task queue中添加一个事件,表示相关异步任务可以进入“执行栈”了。主线程读取task queue,就是读取里面有哪些事件。

    所以同步任务都在主线程上执行,行程一个执行栈。一旦执行栈中所有的同步任务执行完毕,系统就会去读取task queue,看看里面有哪些事件。对应的异步任务,就会结束等待状态,进入执行栈,开始执行。

    微任务优先级高于宏任务,先找微任务,微任务只要还有,则继续按微任务,一直到没有微任务,才去执行宏任务。宏任务的优先级是按照谁先到达执行时间。

    任务队列 task queue

    任务队列分为2中队列

    • macro-task queue: 存放宏任务
      • script
      • setTimeout、setInterval、setImmediate
      • ajax
      • 事件回调
    • micro-task queue:存放微任务
      • Promise.then()、catch()、 finally()、async/await:async函数中的await紧跟函数/语句之后的内容
      • process.nextTick
      • MutaitonObserver:构造器,用来观察node(节点)变化的。

    microtask的执行注意点:

    • async函数中:await紧跟函数/语句之后的内容是异步的,会插入到该microtask队列的末尾
    • 对于then的链式调用,只有当前then的上一个then执行完毕之后,当前then才会被加入微任务队列(而不是立即执行,仅仅只是加入队列)
    • 如果在执行 microtask(微任务) 的过程中,又产生了microtask,那么会加入到队列的末尾,也会在这个周期被调用执行。
    • new Promise里面内容直接运行的
    • .then是否执行和promise中是否有返回值相关(resolve或者是return)。
    • .then执行时,会等之前宏任务执行完成后,延迟执行,并且参数和resolve返回的参数相关联 => .then里面的内容是异步的,是微任务,要等同步代码执行完,去microtask queue中依次执行
    • Promise中resolve的结果,一经确认就不再修改。

    例子:

    new Promise( resolve => {
      console.log(1);
    }).then( res => {
      console.log(2);
    });
    console.log(3);
    
    // 1 3
    // 该Promise并没有return或者resolve,那么then里面的代码是不会执行的。
    
    new Promise( resolve => {
      console.log(1);
      resolve()
    }).then( res => {
      console.log(2);
    });
    console.log(3);
    
    // 1 3 2
    
    new Promise( resolve => {
      console.log(1);
      resolve()
    }).then( res => {
      console.log(res);
    });
    console.log(3);
    
    // 1 3 undefined
    // then里面的参数跟resolve的参数或者return的值有关
    
    new Promise( (resolve,reject) => {
      console.log(1);
      resolve(2)
      resolve(3)
      reject(4)
    }).then( res => {
      console.log(res);
    }).catch( res => {
      console.log(res)
    }).finally(() => {
      console.log('finally')
    });
    console.log(3);
    
    // 1 3 2 finally
    
    new Promise( (resolve,reject) => {
      console.log(1);
      resolve()
      resolve(3)
      reject(4)
    }).then( res => {
      console.log(res);
    }).catch( res => {
      console.log(res)
    }).finally(() => {
      console.log('finally')
    });
    console.log(3);
    
    // 1 3 undefined finally
    
    // Promise中resolve的结果,一经确认就不再修改
    

    Promise和setTimeout结合(微任务、宏任务)

    • 在执行下一个宏任务之前,先清空当前微任务 => 同步任务 --> 微任务 --> 宏任务
    console.log('start');
    new Promise( (resolve,reject) => {
      console.log('promise');
      resolve('then')
      reject('reject')
      setTimeout( () => {
        console.log('setTimeout')
      },)
    }).then( res => {
      console.log(res);
    }).catch( res => {
      console.log(res)
    });
    console.log('end');
    
    // start promise end then setTimeout
    
    // 先执行同步任务: 
    // console.log('start'); console.log('promise');(碰到resolve('then'),异步微任务挂起,等该异步微任务有结果后,将该结果消息推入microtask queue中,等待同步执行完再清空microtask queue)(碰到reject,挂起)(碰到setTimeout,宏任务挂起,等该宏任务执行完有结果后,将该任务消息推入 macrotask queue中,等待微任务全部清空后,再进行宏任务进入主线程)console.log('end');
    // 同步任务执行完毕,清空mircotask queue
    //  console.log('then');
    // 清空mircotask queue之后,开启下一个宏任务
    //  console.log('setTimeout')
    
    
    new Promise( (resolve,reject) => {
      setTimeout( () => {
        console.log('setTimeout')
        resolve('then')
      },)
      resolve('then')
    }).then( res => {
      console.log(res);
    })
    // then setTimeout
    
    new Promise( (resolve,reject) => {
      console.log('promise')
      setTimeout( () => {
        console.log('setTimeout')
        resolve('then')
      },)
    }).then( res => {
      console.log(res);
    })
    // promise setTimeout then
    
    var promise1 = ()=>(
      new Promise( (resolve,reject) => {
        console.log('promise1');
        promise2().then( res => {
          console.log(res)
          console.log("promise2-then")
        })
        setTimeout( () => {
          console.log('setTimeout');
          resolve('then1');
        },);
      })
    );
    
    var promise2 = () => (
      new Promise( resolve =>{
        console.log('promise2');
        resolve('then2');
      })
    );
    
    promise1().then( res => {
      console.log(res);
    });
    // promise1 promise2 then2 promise2-then setTimeout then1
    
    // 同步任务:=> promise1 promise2
    // 1. promise1() => 
    // 		1.1 console.log('promise1');
    // 		1.2 promise2() => console.log('promise2'); 挂起 微任务 resolve('then2')
    // 		1.3. promise2().then( res => {console.log(res)console.log("promise2-then")}) =>  挂起 微任务 promise2().then
    // 		1.4. setTimeout => 挂起宏任务setTimeout
    // 2. promise1().then( res => { console.log(res); }); => 挂起 微任务 promise1().then
    // => promise1 promise2
    
    // 清空微任务 microtask queue  => then2 promise2-then
    // 1. 挂起的1.2 跟 1.3 任务执行有结果了: console.log(res) console.log("promise2-then") 这里的res就是1.2传入的'then2'  => console.log('then2') console.log("promise2-then")
    // 2. 挂起的2没有结果: console.log(res), 这里的res 没有resolve传入参数,所以这个微任务不能清空
    // => then2 promise2-then
    
    // 进行宏任务  => setTimeout
    // 1.  setTimeout( () => {console.log('setTimeout');resolve('then1');});
    // 同步代码: console.log('setTimeout')
    // 挂起微任务resolve('then1');
    // => setTimeout
    
    // 清空微任务:=> then1
    // resolve('then1') => 上一轮的微任务2【挂起的2没有结果: console.log(res) 】得到了返回结果, console.log('then1')
    // => then1
    
    
    // promise1 promise2 then2 promise2-then setTimeout then1
    
  • 相关阅读:
    文件的上传
    扩展HTTP管道
    发布开源框架iOS矢量图形框架 TouchVG
    批量修改文件名的py脚本
    《矢量绘图基础》PPT
    开题了《面向移动设备的交互式图形平台设计与实现》
    计算几何(转)
    批量替换文件名和内容的Python脚本
    iOS上的二维绘图软件现状
    基本图形手绘图形算法包
  • 原文地址:https://www.cnblogs.com/shine-lovely/p/14926096.html
Copyright © 2011-2022 走看看