什么是async,什么是await,async和await的区别,async和await的理解

学完了Promise,我们知道可以用then链来解决多层回调问题,但是这还不是最理想的操作,我们需要调用很多个then链才能达到要求,那么有没有一种更简便代码量更少的方式达到then链相同的结果呢?async和await就很好地解决了这个问题,首先用async声明一个异步函数,然后再用await等待异步结果,把以前then链的结果放到直接放在await,非常方便。

那么,async和await原理是什么呢?为什么可以用这样的语法来优化then链呢?

那么async/await是什么呢?

        async/await其实是Promise的语法糖,它能实现的效果都能用then链来实现,也可以说它是为优化then链而开发出来的。从字面上来看,async是异步的简写,await是等待的意思,await 用于等待一个异步任务执行完成的结果。因此,我们可以总结出来:

  1. async/await 是一种编写异步代码的新方法(以前是采用回调和 promise)。
  2. async/await 是建立在 promise 的基础上。
  3. async/await 像 promise 一样,也是非阻塞的。
  4. async/await 让异步代码看起来、表现起来更像同步代码。

 一:只使用anysc

        我们可以一起来看一下async,async修饰的函数就是异步函数,该函数的返回值是promise对象。

//async修饰的函数就是异步函数,该函数的返回值是promise对象。    
    async function funA() {
        return ("hellow,我是小妲己")
    }
    let p1 = funA();
    console.log(p1);//打印出来的p1是一个promise对象

        上面代码的打印结果:

         

        async修饰函数后,函数的返回值是promise对象,因此,它也是可以使用then方法:

    async function funA() {
        return ("hellow,我是小妲己")
    }
    let p1 = funA();
    console.log(p1);//promise对象
    p1.then(function(str) {
        console.log("then", str);//then hellow,我是小妲己  
    });

         那么,如果我们想要用promise来实现上述代码,应该是怎么写的呢?一起来看看吧:

    function funA() {
        return new Promise(function(resolve, reject) {
            resolve("hellow,我是小妲己")
        })
    }
    funA().then(function(str) {
        console.log("funA", str); //funA hellow,我是小妲己
    })

         由上面代码我们可以看到,它们的执行结果是一样的。那么进一步说明了:

        Async修饰的函数的返回值会作为resolve对应函数的参数。

二:使用async和await结合,获取resolve里面的值

        首先,await只能写在async修饰的函数里。

        Await是等待的意思,await修饰的代码会等待。在函数里,碰到await修饰的代码时,await朝后的代码都会等待。也就是说,必须得等待await后面的Promise处理完成才能继续。

        一般来说:await后面接一个Proimse对象,或者返回Promise对象的函数。

await 修饰函数后,那么,返回值变成了Promise对象中resolve的参数。

    我们来写一个示例:

    async function fn() {
        console.log("await前");
        // await 修饰的 Promise对象的返回值是 resolve的参数,所以我们不用再写then了。 
        let res = await new Promise((resolve, reject) => {
            setTimeout(function() {
                resolve("欢迎来到");
            }, 1000)
        });
        //res就相当于拿到了resolve中的参数
        console.log("await后:" + res); //await后:欢迎来到
    }
    fn();
    console.log('虽然在后面,但是我先执行');

        上面代码中,我们可以await后面的Promise对象写在一个函数里。

    function testf() {
        return new Promise((resolve, reject) => {
            setTimeout(function() {
                resolve("欢迎来到");
            }, 1000);
        });
    }
    async function fn() {
        console.log("await前");
        // await 修饰的 Promise对象的返回值是 resolve的参数,所以我们不用再写then了
        let res = await testf();
        console.log("await后:" + res); //await后:欢迎来到
    }
    fn();
    console.log('虽然在后面,但是我先执行');

        可以看到,这样我们依然可以拿到resolve中的参数。

三:使用anysc和await结合,获取reject里面的值

        使用try catch

        格式:       

    try{
    // 若干句代码;这些代码里,只要碰到错误,就会跳到catch里。即就是:碰到错误后,try里处于错误行后面的代码不再执行。
    }catch(){
    //  出错,
    }
//===================================如============================
    try {
        let res1 = await ajax();
        // res1就是 resolve的参数
        let res2 = await ajax();
        // res2就是 resolve的参
    } catch (err) {
        //err: 如果说第一次ajax请求失败, 那么err就是第一次ajax请求里reject的参数;
        // 如果说第二次ajax请求失败, 那么err就是第二次ajax请求里reject的参数
    }

         示例一:

  function getFn() {
        return new Promise((resolve, reject) => {
            setTimeout(function() {
                if (false) {
                    resolve("hhhh");
                } else {
                    reject("出错了");
                }
            }, 1000)
        })
    }
    async function fn() {
        console.log("await前")
        try {
            let res = await getFn();
            console.log("await后(成功):" + res) //此处拿到的是resolve的参数;
        } catch (error) {
            console.log("await后(失败):" + error) //此处拿到的是reject的参数
        }
    }
    fn();

        示例二:发送两个ajax请求,两个ajax请求放在同一个try catch里,那么,哪个出错了,catch里拿到的就是哪个里的reject的参数。

    try {
        let sendStr = `username=${$("username").value}&userpass=${$("userpass").value}`;
        let res = await ajax03({
            method: "post",
            ​url: "loginCheck03.php",
            ​params: sendStr
       });
        success(res);
        let res2 = await ajax03({
           url: "loadMore.php",
           ​params: "pageIndex=2"
        });
        show(res2);
       } catch (error) {
        console.log("error:", error); //第一次请求出错,那么拿到的就是第一次请求的reject的参数;第二次出错,就是第二次的reject的参数;
      }

总结一下:async/await的优点

        1.方便级联调用:即调用依次发生的场景;
        2.同步代码编写方式:Promise使用then函数进行链式调用,一直点点点,是一种从左向右的横向写法;async/await从上到下,顺序执行,就像写同步代码一样,更符合代码编写习惯;
        3.多个参数传递:Promise的then函数只能传递一个参数,虽然可以通过包装成对象来传递多个参数,但是会导致传递冗余信息,频繁的解析又重新组合参数,比较麻烦;async/await没有这个限制,可以当做普通的局部变量来处理,用let或者const定义的块级变量想怎么用就怎么用,想定义几个就定义几个,完全没有限制,也没有冗余工作;
        4.同步代码和异步代码可以一起编写:使用Promise的时候最好将同步代码和异步代码放在不同的then节点中,这样结构更加清晰;async/await整个书写习惯都是同步的,不需要纠结同步和异步的区别,当然,异步过程需要包装成一个Promise对象放在await关键字后面;
        5.基于协程:Promise是根据函数式编程的范式,对异步过程进行了一层封装,async/await基于协程的机制,是真正的“保存上下文,控制权切换……控制权恢复,取回上下文”这种机制,是对异步过程更精确的一种描述;
        6.async/await是对Promise的优化:async/await是基于Promise的,是进一步的一种优化,不过在写代码时,Promise本身的API出现得很少,很接近同步代码的写法。

总结一下:async/await的缺点

        缺点在于滥用 await 可能会导致性能问题,因为 await 会阻塞代码,也许之后的异步代码并不依赖于前者,但仍然需要等待前者完成,导致代码失去了并发性 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只小可乐吖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值