• 宏任务和微任务


    宏任务与微任务

    事件循环

            javascript语言是一个单线程语言,那就意味着在同一时间js只能干一件事(虽然在h5新增了线程的概念但是js还是一个单线程语言),为了能让代码运行时不会阻塞,Event Loop执行机制被js引用。在执行代码时一个个任务根据一定的规则压入栈顶。而这些函数有异步和同步之分,同步很好理解一个个排队执行,异步是可以在等待某个函数的同时可以做别的函数。举个简单的例子:我们正在写代码的时候,电话突然说我的外卖到了。同步的话,我们只能写代码和领外卖做一个。而异步的话就是我们让我们的室友帮我们去拿或写代码,这两件事可以同时做。而异步任务中又有宏任务和微任务,接下来我就来分享一下宏任务和微任务。

    宏任务

          宏任务可以被理解为每次"执行栈"中所执行的代码,而浏览器会在每次宏任务执行结束后,在下一个宏任务执行开始前,对页面进行渲染,而宏任务包括:

    script(整体代码)
    setTimeout
    setInterval
    I/O
    UI交互事件
    postMessage
    MessageChannel
    setImmediate(Node.js 环境)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    特别注意 Promis是异步但是new Promise在实例化的过程中所执行的代码都是同步进行的,而then中注册的回调才是异步执行的。

    而且async/await底层是基于Promise封装的,所以await前面的代码相当于new Promise,是同步进行的,await后面的代码相当于then,才是异步进行的。

    微任务

                 微任务是在宏任务执行完立刻执行微任务,而微任务包括:

    Promise.then
    Object.observe
    MutationObserver
    process.nextTick(Node.js 环境)
    
    • 1
    • 2
    • 3
    • 4

    执行流程

    在这里插入图片描述
    从宏任务开始执行

    代码演示

    1、案例一
    console.log(1);
    setTimeout(()=>{
        console.log(5)
    },0)
    //这里的Promise对象实例化是同步执行,而.then方法是异步任务
    new Promise((resolve, reject)=>{
        console.log(2)
        resolve()
    }).then(()=>{
        console.log(4)
    })
    console.log(3);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    执行讲解:

    先输出1,之后遇到宏任务setTimeOut压入宏任务消息队列,之后遇到Promise对象实例化是同步的,输出2,随后遇到then方法是微任务压入微任务消息队列,之后输出3,宏任务执行完去执行微任务,输出4,微任务执行完去执行宏任务输出5。最终代码执行完。

    2、案例二
    console.log(1)
    setTimeout(()=>{
        console.log(3)
        new Promise((resolve, reject)=>{
            console.log(4)
            resolve()
        }).then(()=>{
            console.log(5)
        })
    },0)
    setTimeout(()=>{
        console.log(6)
        new Promise((resolve, reject)=>{
            console.log(7)
            resolve()
        }).then(()=>{
            console.log(8)
        })
    },0)
    console.log(2)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    执行讲解:

    先输出1,之后遇到第一个宏任务setTimeout,压入宏任务消息队列,随后遇到第二个宏任务setTimeout,压入宏任务消息队列,输出2,宏任务执行完并没有微任务,去执行第一个宏任务,输出3,这里的Promise对象的实例化也是同步执行,输出4,发现微任务then()压入微任务消息队列,这里执行完去执行微任务输出5,第二个宏任务setTimeout和第一个类似,依次输出6,7,8

    实际上就是上边图片的循环执行方式

    3、案例三
    console.log(1)
    setTimeout(()=>{
        console.log(7)
    },0)
    new Promise((resolve, reject)=>{
        console.log(2)
        resolve()
    }).then(()=>{
        console.log(4)
        setTimeout(()=>{
            console.log(8)
        },0)
        new Promise((resolve, reject)=>{
           console.log(5)
            resolve()
        }).then(()=>{
            console.log(6)
        })
    })
    console.log(3)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    执行讲解:

    先输出1,发现一个宏任务压入宏任务消息队列(第一个定时器函数),之后实例化promise对象是同步操作,输出2,然后把之后的then方法这个微任务添加到微任务消息队列,随后输出3,外边的任务都执行完了开始执行微任务,输出4,发现一个宏任务压入宏任务消息队列(第二个定时器函数),实例化promise是同步执行输出5,发现微任务,压入微任务消息队列。注意因为这里的then方法(第二个then)是微任务并且已经压入微任务队列,这时微任务消息队列并不是空,会继续执行then方法输出6。这时微任务才算执行完。去执行宏任务,依次输出7和8(任务队列先进先出,第一个定时器先压入队列,第二个后压入,所以先执行输出7在执行输出8)

    总结

    js是单线程的语言。一次只能执行一个任务,我们只要记得它执行的规则,就可以了。有什么不了解的或者我写的不对的地方欢迎提问和指正。

  • 相关阅读:
    Android Studio Dolphin Patch 1 简介及下载地址
    Codeforces Round #835 (Div. 4) F. Quests
    【linux进程(五)】进程间切换以及环境变量问题
    JVM之内存泄漏和内存溢出
    在鹅厂工作1到11年的程序媛
    大二Web课程设计:HTML+CSS学校静态网页设计——南京师范大学泰州学院(11页)
    leetcode刷题(第四十八天) 198.打家劫舍 ; 213.打家劫舍II ; 337.打家劫舍III
    网络-Ajax
    django接口无法通过ip进行访问
    图形推理到底如何推?
  • 原文地址:https://blog.csdn.net/YX0711/article/details/126901264