• 集千篇理论精华,感悟对同步和异步的理解


    一、promise本身是同步还是异步呢?

    众所周知,Promise是ES6提出的解决异步编程导致陷入回调地狱问题的,那么Promise是同步的还是异步的?可以确定的是,Promise本身是同步的,而他的.then和.catch为异步的。
    
    举个栗子:
    console.log(1)
    let a = new Promise((res,rej) => {
       console.log(2);
    });
    console.log(3);
    let b = new Promise((res,rej) => {
        console.log(4);
    });
    console.log(5);                  //1,2,3,4,5

     二、返回的异步代码执行顺序 (.then / .catah)

    console.log(1)
    let a = new Promise((res,rej) => {
        console.log(2);
        res();
    });
    console.log(3);
    let b = new Promise((res,rej) => {
        console.log(4);
        res();
    });
    console.log(5);
    a.then(() => {   //先执行a,是因为.then是一个微任务,而且a最先进入微任务队列,所以现在执行a,在执行b,但都必须是在等到同步代码结束之后在进入执行队列;
        console.log(6)
    })
    b.then(() => {
        console.log(7)
    })



    栗子:
    new Promise( ( resolve, reject ) => {
      console.log( "promise1" )
      resolve()
    } )
    .then( () => {
      console.log( 1 )
    } )
    .then( () => {
      console.log( 2 )
    } )
    .then( () => {
      console.log( 3 )
    } )

    new Promise( ( resolve, reject ) => {
      console.log( "promise2" )
      resolve()
    } )
    .then( () => {
      console.log( 4 )
    } )
    .then( () => {
      console.log( 5 )
    } )
    .then( () => {
      console.log( 6 )
    } )

    promise1
    promise2

    1
    4
    2
    5
    3
    6

     三、宏任务与微任务

    - JS是一种单线程语言,代码执行顺序(同步代码先执行---->等同步代码执行完毕异步代码在执行)主线任务清空之后,异步进入任务队列,开始从任务队列进入到主线程。
    - 异步任务里面又存在宏任务和微任务。(同步代码不存在宏任务与微任务一说)
    - 宏任务:定时器  /   **script**- 微任务:.then
    <script>
            console.log('start');     //同步
    
            setTimeout(()=>{      //宏任务
                console.log('time1');
            })
    
            new Promise((resolve)=>{
                console.log('promise');   //同步
                resolve();
            })
            .then(()=>{               //.then是异步   微任务
                console.log('then');
            })
    
            setTimeout(()=>{     // 宏任务
                console.log('time2');
            })
    
            console.log('外部console');    //同步
            
            </script>
            执行顺序:
            1、首先同步代码先依次执行;
              star,promise 外部console
            2、then,第一个宏任务下的微任务,
            3、time1  time2  宏任务

    注意:在下一个宏任务开始之前,必须将当前主线微任务全部执行完毕,才进入下一个宏任务,也就是所谓的事件循环---eventloop。

                                              

    三、async和await函数

    async 函数是什么?一句话,它就是 Generator 函数的语法糖,async函数就是将 Generator 函数的星号(*)替换成async,将yield替换成await,仅此而已。

    async函数的返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象方便多了。你可以用then方法指定下一步的操作。

    进一步说,async函数完全可以看作多个异步操作,包装成的一个 Promise 对象,而await命令就是内部then命令的语法糖。

    注意await之后的代码必须等await语句执行完成后(包括微任务完成),才能执行后面的,也就是说,只有运行完await语句,才把await语句后面的全部代码加入到微任务行列,
    所以,在遇到await promise时,必须等await promise函数执行完毕才能对await语句后面的全部代码加入到微任务中,所以, 在等待await Promise.then微任务时,
    1.运行其他同步代码, 2.等到同步代码运行完,开始运行await promise.then微任务, 3.await promise.then微任务完成后,把await语句后面的全部代码加入到微任务行列, 4.根据微任务队列,先进后出执行微任
    console.log(1)
    async function async1(){
        console.log('async1 start')
        await async2()           //在此先做返回,将后面所有的代码放到异步队列,
        console.log('async1 end')
      }
    async function async2(){
        console.log('async2')
    }
    async1();
    console.log('i am koala')
    //结果:

    1
    async1 start
    async2
    i am koala
    async1 end

      async 函数返回一个 Promise 对象,(promise 本身为同步代码)

    当函数执行的时候,一旦遇到 await 就会先返回,等到触发的异步操作完成,再接着执行函数体内后面的语句
    async function t1() {
      console.log(1)
      console.log(2)
      await new Promise(resolve => {
        setTimeout(() => {
          console.log('t1p')
          resolve()
        }, 5000)
      })
      await console.log(3)
      console.log(4)
    }
    
    async function t2() {
      console.log(5)
      console.log(6)
      await Promise.resolve().then(() => console.log('t2p'))
      console.log(7)
      console.log(8)
    }
    
    t1()
    t2()
    
    console.log('end')

    1
    2
    5
    6
    end
    t2p
    7
    8
    t1p
    3
    4

    async function async1() {
      console.log( 'async1 start' ) 
      await async2()
      console.log( 'async1 end' )
    }
    async function async2() {
      console.log( 'async2' )
    }
    console.log( 'script start' )    //属于一个同步代码,优先于async返回的promise执行,在async内部!
    setTimeout( function () {
      console.log( 'setTimeout' )
    }, 0 )
    async1();
    new Promise( function ( resolve ) {
      console.log( 'promise1' )
      resolve();
    } ).then( function () {
      console.log( 'promise2' )
    } )
    console.log( 'script end' )

    //执行结果

    script start
    async1 start
    async2
    promise1
    script end
    promise2
    async1 end
    setTimeout

    async function t1 () {
      console.log(1)                               //1
    console.log(2)                                //2
      new Promise( function ( resolve ) {             
      console.log( 'promise3' )              //3
      resolve();
      } ).then( function () {
      console.log( 'promise4' )
      } )
      await new Promise( function ( resolve ) {       //如果它等到的是一个 promise 对象,await 也会暂停async后面的代码,先执行async外面的同步代码,
                                                      //等着 Promise 对象 fulfilled,然后把 resolve 的参数作为 await 表达式的运算结果
      console.log( 'b' )                    //4
    
      resolve();
      } ).then( function () {
      console.log( 't1p' )
      } )
      console.log(3)                  
      console.log(4)                  
      new Promise( function ( resolve ) {
      console.log( 'promise5' )      
      resolve();
      } ).then( function () {
      console.log( 'promise6' )
      } )
      }
      setTimeout( function () {
      console.log( 'setTimeout' )
      }, 0 )
    
      async function t2() {
      console.log(5)
      console.log(6)
      await Promise.resolve().then(() => console.log('t2p'))  //属于promise方法,不是对象!
      console.log(7)
      console.log(8)
      }
      t1()
      new Promise( function ( resolve ) {
      console.log( 'promise1' )       //同步代码
      resolve();
      } ).then( function () {
      console.log( 'promise2' )
      } )
      t2()
    
      console.log('end');

    //执行结果;

    1
    2
    promise3
    b
    promise1
    5
    6
    end
    promise4
    t1p
    promise2
    t2p
    3
    4
    promise5
    7
    8
    promise6
    setTimeout

     分析:

     当遇见第一个await之后,阻止后面的承誉德执行,加入微任务队列;执行其他同步代码,但是5,6先于end之前执行,是因为t2在end之前调用。

    总结:
    await后面如果等到的是promise对象,执行完resolve之后,阻止后面程序的运行,加入微任务队列,
    如果是promise方法,也就是不是promise对象的时候,同样也阻止后面的程序的运行,也加入微任务队列。

     

    要有最平凡的生活,和最遥远的梦想,即使明天天寒地冻,路遥马亡……

  • 相关阅读:
    PHP数字签名算法
    PHP日期相关类
    浏览器常见bug及解决办法
    PHPer整理的前端开发知识
    小程序之轮播图(2020.4.13更新)
    Android APK反编译 apktool使用教程
    秒懂-单列布局水平居中布局
    一句话搞定-phpStudy安装yaf扩展
    Git的简单安装
    人人都能读懂的css3 3d小demo
  • 原文地址:https://www.cnblogs.com/gzw-23/p/11802303.html
Copyright © 2020-2023  润新知