zoukankan      html  css  js  c++  java
  • JS 事件循环机制(宏任务、微任务)

    执行代码的先后顺序:

    先 主任务 后 任务队列。

    任务队列又分:微任务(Microtasks)、宏任务(task)

    • 微任务:先注册的任务先执行(先进先出)。比如:Promise.then 、process.nextTick
    • 宏任务:比如:整体代码<script>、ajax、定时器(比如:setTimeout)、事件(比如:onclick)、requestAnimationFrame(帧动画)、I/O(文件操作)、UI rendering(样式渲染)

    任务队列既有宏任务又有微任务,先执行微任务,再执行宏任务。

    主任务(主线程,执行完之后会去任务队列里读取可执行的任务进入主线程)
      ↓
    任务队列:微任务(清空一次) ------> 宏任务(每执行一个清空一次微任务)
                ↑_________循环执行________|
    

    这种循环机制叫做:事件循环(event loop)

    主线程-微任务-宏任务 练习:(如何使用async、await、Promise以及各种任务的执行特点)

    async function fn() {
      console.log(1);
      let b = await fn2();//b拿到return的值 = resolve()里面的值,并阻塞下面的代码。
      console.log(b);
      console.log(2)//出现在await之后,也就是2一定跟着3之后出现
    };
    function fn2() {
      return new Promise((resolve, reject) => {//async、await要配合Promise使用。
          console.log(9);
          setTimeout(() => {
              resolve(3)//进入宏任务,定时器谁先触发谁先执行。
          }, 1000)
      });
    }
    // async function fn() {
    //     //function fn() {
    //     console.log(1);
    //     let b = await fn2();
    //     console.log(2)//进入微任务,谁先进入谁先触发。
    // };
    // function fn2() {
    //     console.log(9);
    //     setTimeout(() => {
    //         resolve(3)//进入宏任务,定时器谁先触发谁先执行。
    //     }, 1000)
    // };
    
    setTimeout(() => {
      console.log(6)//进入宏任务
    }, 500);
    fn()
    let a = new Promise((resolve, reject) => {
      console.log(4);
      resolve()
    })
    a.then(() => {
      console.log(5)//进入微任务
    });
    //fn()
    console.log(8);
    //1,9,4,8,2,5,3,6
    //4,1,9,8,5,2,3,6
    //注:如果await后面的函数,没有被Promise包着。 await 下面的代码会进微任务队列(谁先进入谁先执行),定时器会进宏任务队列(谁先触发谁先执行)。
    //1,9,4,8,5,6,3,2
    //await后面的函数被Promise包着,那么await后面的函数才会阻塞下面的函数,等await后面的函数执行完,再往下执行(只在函数体内发生)。
    

    面试题一:

    let body = document.body;
    body.addEventListener('click', function () {
        Promise.resolve().then(() => {
            console.log(1);
        });
        console.log(2);
    });
    body.addEventListener('click', function () {
        Promise.resolve().then(() => {
            console.log(3);
        });
        console.log(4);
    });
    

    面试题二:

    async function async1() {
        console.log('async1 start');
        await async2();
        console.log('async1 end');
    }
    async function async2() {
        console.log('async2');
    }
    console.log('script start');
    setTimeout(function () {
        console.log('setTimeout');
    }, 0)
    async1();
    new Promise(function (resolve) {
        console.log('promise1');
        resolve();
    }).then(function () {
        console.log('promise2');
    });
    console.log('script end');
    

    思考?await 下面被阻断的代码,那这一部分代码是如何执行的?

    • await 后面如果是微任务(一个promise),它下面的代码就会等待这个微任务执行完,紧跟着执行。
    • await 后面如果是主任务(比如一个函数或一个表达式),其下面的代码就会等待这一批主任务执行完,最后执行。
  • 相关阅读:
    本周读书的感想
    程序员应知——学习、思考与分享
    用设计版面的思想编写漂亮的代码
    程序员应知——你有几种武器
    《明星DBA成长之路》读后随想
    有些东西不可替代
    DB2连接串&DB2客户端连接服务端
    数据库连接字符串备忘大全
    ASP Blob类型转存为Long Raw类型
    Oracle read_csv
  • 原文地址:https://www.cnblogs.com/MrZhujl/p/15072137.html
Copyright © 2011-2022 走看看