async/await

一、异步的实现:

1、 使用异步回调,但有callback hell (回调地狱)的风险,所以为了解决这个回调地狱的问题采用了Promise

2、Promise then catch 链式调用,但也是基于回调函数的

3、async/await 是用同步的语法来编写异步代码,彻底消灭回调函数

二、async/await 和 Promise 的关系

  • async/await 是消灭异步回调的终极武器,用同步代码的方式实现异步
  • async/await 和 Promise并不互斥,反而两者相辅相成
  • 执行 async 函数,返回的是Promise对象
  • await 相当于Promise 的then
  • async/await  使用 try...catch 捕获异常;代替了Promise 的 catch

举例说明:

  1. 执行 async 函数,返回的是Promise对象

  async函数里面的 return 如果不是一个Promise(是一个值,或者没有返回),那么会按照return Promise.resolve(值) 处理

           async function fn1(){
               // return 100 //相当于 Promise.resolve(100)
                return Promise.resolve(200)
            }
            const res1 = fn1() //执行async 函数返回的是 Promise 对象
            console.log(res1,'res1') //Promise 对象
            res1.then(data=>{
                console.log(data,'data') // 100
            })

  2. await 相当于 Promise 的 then

  await 后面如果是一个值,可以看作是Promise.resolve(值)

  await 返回的值相当于执行了 Promise.then。所以返回的就是 Promise.then 里面的值

           async function fn1(){
                return Promise.resolve(200)
            }

          !(async function (){
                const p1 = Promise.resolve(300) // p1 是一个Promise 对象
                const data = await p1  //await 相当于 Promise then
                console.log(data) // 300  
            })()
            !(async function (){
                const data = await 400  // 相当于 await Promise.resolve(400) then
                console.log(data) // 400  
            })()
            !(async function (){
                const data = await fn1()  // 相当于 await Promise.resolve(200) then
                console.log(data) // 200  
            })()
        </script>

  2.async/await  使用 try...catch 捕获异常

    async 函数中使用await后,就没办法取到错误信息或者Promise.reject('信息') 返回的信息(因为上面我们知道 awiat 相当于Promise.then)。

    我们可以使用try....catch 来不会异常信息,代替了Promise.reject

          !(async function(){
                try{
                    const p4 = Promise.reject('错误') // 状态为rejected 的 Promise
                    console.log(1)
                    let data = await p4 // await 相当于 Promise then ;此处会抛出错误进入catch中,下面的代码都不会执行
                    console.log(data,'22') // 此处不会执行
                }catch(ex){
                    console.log(ex)
                }
            })()

  执行结果为: 1  '错误'

三、async/await 异步本质 还是回调函数

  1、上面提到async/await 是消灭异步回调的终极武器,但JS还是单线程,还是有异步的,所以还是要基于Event Loop。并不是有了async/await 就没有异步了

  2、async/await只是一个语法糖,只是以同步代码的写法实现了异步

  3、await 下面的代码可以看作是异步的回调函数,需要等同步代码执行完,开启event loop 把回调函数放到调用栈(call stack) 中执行

  看个例子,更好地理解async await 执行过程

         async function fn1(){
                console.log(1)
                await fn2() 
                //awiat 后面的相当于异步回调函数,需要同步执行完,再通过event loop 执行
                console.log(2)
                await fn3()
                //await 后面的相当于异步回调函数
                console.log(3)
            }
            async function fn2(){ 
                console.log(4)
            }
            async function fn3(){
                console.log(5)
            }
            console.log(6)
            fn1()
            console.log(7)

  分析:

    1. console.log(6) 输出6,然后调用fn1()

    2. fn1中 第一行直接打印 1,遇到await fn2() 会立即执刑 fn2(),并且await fn2() 后面的代码相当于异步回调函数,放到了微任务队列中等待执行

    3. fn2() 直接打印 4

    4. 继续执行 同步代码console.log(7),打印 7

    5、至此同步代码执行完,调用栈为空,开始事件循环,微任务队列里的回调函数方法放到调用栈中执行

    6、执行console.log(2),输出 2

    7. 执行 await fn3() ,会立即执行fn3(),同时将后面的代码 放到微任务队列中

    8. 执行 fn3(),打印 5

    9、至此调用栈为空,开始进入又一次事件循环,执行微任务队列中的回调函数 

    10、执行 console.log(3),打印3

所以最终输出: 6 1 4 7 2 5 3  

posted @ 2024-11-25 16:29  yangkangkang  阅读(4)  评论(0编辑  收藏  举报