• Javascript的同步与异步,异步的宏任务与微任务——事件循环


    JavaScript是单线程:

    同一时间只能干一件事情,只有前面的事情执行完,才能执行后面的事情。导致遇到耗时的任务时后面的代码无法执行,这就会影响到执行过程,致使阻塞。

    为了解决这个问题,Js将任务分为了同步与异步

    什么是同步任务?

    按顺序挨个执行的

    1. console.log(123);
    2. for (let i = 1; i <= 5; i++) {
    3. console.log(i);
    4. }
    5. console.log(456);

    先输出123,再输出1,2,3,4,5,最后输出456,按代码从上到下的顺序执行的

    什么是异步任务?

    首当其冲想到的就得是定时器(setTimeout、setInterval)了吧,当然还有Ajax的数据请求、async-await、promise、读写文件等

    1. setTimeout(()=>{
    2. console.log('定时器');
    3. },0)
    4. console.log(1)

    虽然定时器在前,虽然定时器是0s,但由于其属于异步任务,会先存到任务队列中等待执行

    同步与异步相遇,优先执行同步任务,所有的同步任务都在主线程上依次执行,形成一个【执行栈】。

    执行栈外还有个任务队列:在执行同步任务时也不是对异步置之不理了,异步任务一旦有了运行结果就会在【任务队列】中放置一个事件。当执行栈中的同步任务都执行完了,才会开始读取【任务队列】,看其中有哪些事件,将这些事件放入执行栈开始执行。

    怎么执行任务?

    在执行异步任务时,还要明白一个概念就是:宏任务与微任务

    宏任务有:script标签,setTimeout,setInterval

    微任务有:Promise,nextTick

    也就是说在在异步任务里也论资排辈的,会先走微任务,再走宏任务

    1. setTimeout(() => {
    2. console.log('定时器');
    3. }, 0)
    4. new Promise((resolve) => {
    5. console.log('同步代码')
    6. resolve('异步代码')
    7. }).then((res) => {
    8. console.log(res);
    9. })
    10. console.log('奥特曼');

    输出:同步代码、奥特曼、异步代码、定时器

    啥意思呢?

    首先最底下的输出是同步无疑,但为啥先输出“同步代码”,不是说promise是异步吗?

    promise确实是异步,但new Promise是创建一个构造函数,这个过程是同步的

    promise的异步是在说它的回调函数上:.then()    .catch()

    所以new Promise下的第一层的输出是同步,和最下面的输出同一级别,按照从上到下顺序,所以先执行。

    这个时候注意了,就剩下了定时器和Promise的回调函数.then(),那这俩怎么看顺序呢?

    就要用到微任务与宏任务的对比了

    Promise的回调是微任务,setTimeout的回调是宏任务,所以先执行Promise的代码

    最后总结下来就是:同步优先与异步(异步中又分:微任务优先于宏任务)

    事件循环?

    宏任务里既存在微任务,又存在宏任务。

    执行这个宏任务时又要将微任务和宏任务分开,又要来一个任务队列来分装微、宏任务

    这个过程就可以叫事件循环

    1. // 一级·异步
    2. setTimeout(()=>{
    3. // 二级·宏任务
    4. setTimeout(()=>{// 二级·宏任务回调
    5. console.log("定时器里的定时器")
    6. },0)
    7. // 二级
    8. new Promise((resolve,reject)=>{
    9. // 同步
    10. console.log("promise")
    11. resolve("promise的resolve");
    12. }).then((res)=>{// 异步·微任务---要给下面的二级同步代码让路
    13. console.log(res)
    14. // 三级·宏任务
    15. setTimeout(()=>{// 三级·宏任务回调
    16. console.log('promise的定时器')
    17. },0)
    18. })
    19. // 二级·同步
    20. console.log('haha')
    21. },0)
    22. // 一级·同步
    23. console.log('111')

    输出:111、promise、haha、promise的resolve、定时器里的定时器、promise的定时器

    同级宏任务要给微任务让路,次级任务要给上级任务让路(promise定时器vs定时器的定时器)

    注意:

    两个同级定时器,延迟时间少的会优先放到主线程里执行

    两个同级定时器,延迟时间一样的会按顺序执行

    练习

    1. console.log('1');
    2. setTimeout(function () {
    3. console.log('2');
    4. process.nextTick(function () {
    5. console.log('3');
    6. })
    7. new Promise(function (resolve) {
    8. console.log('4');
    9. resolve();
    10. }).then(function () {
    11. console.log('5')
    12. })
    13. })
    14. process.nextTick(function () {
    15. console.log('6');
    16. })
    17. new Promise(function (resolve) {
    18. console.log('7');
    19. resolve();
    20. }).then(function () {
    21. console.log('8')
    22. })
    23. setTimeout(function () {
    24. console.log('9');
    25. process.nextTick(function () {
    26. console.log('10');
    27. })
    28. new Promise(function (resolve) {
    29. console.log('11');
    30. resolve();
    31. }).then(function () {
    32. console.log('12')
    33. })
    34. })

    输出:1、7 、6、8、2、4、3、5、9、11、10、12

  • 相关阅读:
    三剑客之 grep
    java调用jni全流程,简洁易懂!
    【第2章 Node.js基础】2.5 Node.js 的定时器
    【再探】Java — 面向对象编程特性与内部类
    危险边缘:揭示 Python 编程中易被忽视的四个安全陷阱
    四嗪-一聚乙二醇-炔末端炔烃/3,6-二氨基 -1,2,4,5-四嗪修饰多壁碳纳米管应用
    字符检测专题第一期:OCR技术工业应用浅谈
    番外 2 : LoadRunner 的安装以及配置
    避坑版-OpenSSH 用户名枚举漏洞(CVE-2018-15473)
    中国石油大学(北京)-《汽车保险与理赔》作业
  • 原文地址:https://blog.csdn.net/qq_38800316/article/details/125515732