zoukankan      html  css  js  c++  java
  • ES6之async await

    含义

    • 内置执行器
      • Generator函数的执行必须靠执行器,所以才有了co模块,而async函数自带执行器。也就是说,async函数的执行,与普通函数一模一样,只要一行fn()
    • 更好的语义
      • async和await,比起星号和yield,语义更清除了。async表示函数里又异步操作,await表示紧跟在后面的表达式需要等待结果。
    • 更广的适用性
      • co模块规定,yield命令后面只能时Thunk函数或Promise对象,而async函数的await命令后面,可不是Promise对象和原始类型的值(数值、字符串和布尔值,但这时会自动转成立即resolved 的Promise对象)
    • 返回值时Promise
      • async函数的返回值时Promise对象,这比Generator函数的返回值是Iterator对象方便多了。你可以用then方法制定下一步操作。

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

    基本用法

    async函数返回一个Promise对象,可以使用then方法添加回调函数。当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,在接着执行函数体后面的语句

        async function fn(){
            console.log(4)
            let f1 = await Promise.resolve(1)
            console.log(f1) // 1
            let f2 = await Promise.resolve(2)
            return f2
        }
        fn().then(res=>{
            console.log(res) // 2
        })
        console.log(3)
        // 4  3  1  2
    

    上面代码中,函数前面的async关键字,表示函数内部有异步操作。调用该函数时,会立即返回一个Promise对象。

        function timeout(ms){
            return new Promise((resolve)=>{
                setTimeout(resolve,ms)
            })
        }
        async function fn(value,ms){
            await timeout(ms)
            console.log(value)
        }
        fn('haha',3000)
    

    上面代码会在3秒后输出haha

    async函数有多种使用形式。

        // 函数声明
        async function fn(){}
        // 函数表达式
        let fn1 = async function(){}
        // 对象的方法
        let obj = {async foo(){}}
        obj.foo().then(()=>console.log(111)) // 111
        // class 的方法
        class fn2{
            constructor(name){
                this.name = name;
            }
            async getName(){
                return this.name
            }
        }
        let name = new fn2('小明');
        name.getName().then(res=>console.log(res)) // 小明
    

    语法

    async函数返回一个Pormise对象。
    async函数内部return语句返回的值,会成为then方法回调函数的参数

        let fn = async function(){
            return 111
        }
        fn().then(res=>{console.log(res)}) // 111
    

    上面代码,函数fn返回的值,会被then放回回调函数接收到

    async内部抛出错误,会导致返回的Promise对象变为reject状态。抛出的错误对象会被catch方法回调函数接收到。

        let fn = async function(){
            throw new Error('出错了')
        }
        fn().catch(error=>{
            console.log(error); // Error: 出错了
        })
    
    Promise对象的状态变化

    async函数返回的Promise对象,碧玺等到内部所有await命令后面的Promise对象执行完,才会发生状态改变,除非遇到return语句或者抛出错误。也就是说,只有asunc函数内部的异步操作执行完,才会执行then方法指定的回调函数。

        let fn = async function(){
            await new Promise((resolve)=>{
                setTimeout(resolve,3000)
            })
            await new Promise((resolve)=>{
                setTimeout(resolve,3000)
            })
            return 1
        }
        fn().then(res=>{
            console.log(res);
        })
    

    上面代码,then回调函数会在6秒之后输出res

    await

    正常情况下,await命令后面是一个Promise对象,返回该对象的结果。如果不是Promise对象,就直接返回对应的值

        let fn = async function(){
            // 等同于
            // return 1
            return await 1
        }
        fn().then(res=>{
            console.log(res); // 1
        })
    

    上面代码中,await命令的参数是数值1,这是等同于return 1

        let fn = async ()=>{
            await Promise.reject('出错了')
        }
        fn().catch(error=>{console.log(error)}) // 出错了
    

    注意:上面代码中,await语句前面没有return,但是reject方法的参数依然传入了catch方法的回调函数。这里如果在await前面加上return,效果是一样的

    注意:任何一个await语句后面的Promise对象变为reject,那么整个async函数都会中断执行

    有时,我们希望即使前一个异步操作失败,也不要中断后面的异步操作。这时可以将第一个await放在try...catch结构里面,这样不管这个异步操作是否成功,第二个await都会执行

        let fn = async ()=>{
            try{
                await Promise.reject('出错了')
            }catch(error){
                console.log(error) 
            }
            return 1
        }
        fn().then(res=>console.log(res)) // 1
    

    另一种写法

        let fn = async ()=>{
            await Promise.reject('出错了').catch(error=>{
                console.log(error) 
            })
            return 1
        }
        fn().then(res=>console.log(res)) // 1
    

    错误处理

    如果await后面的异步操作出错,那么等同于async函数返回的 Promise 对象被reject。

        let fn = async ()=>{
            await Promise.reject('出错了')
            return 1
        }
        fn()
        .then(res=>console.log(res))
        .catch(error=>{
            console.log(error) // 出错了
        })
    

    上面代码中,函数fn执行后,await后面的Promise对象抛出了一个错误对象,导致catca方法的回调函数被调用。

    防止出错的方法,也是将其放在try...catch代码块中

        let fn = async ()=>{
            try{
                await Promise.reject('出错了')
            }catch(error){
                console.log(error);
            }
            return 1
        }
        fn()
        .then(res=>console.log(res)) // 1
    

    如果有多个await命令,可以统一放在try...catch

  • 相关阅读:
    go基础_defer
    go基础_函数
    go基础_控制语句
    go基础_数组
    go基础_切片
    go命令行参数
    Hdu2795Billboard线段树
    Hdu1394Minimum Inversion Number线段树
    Hdu1754单点更新
    Hdu1166单点更新线段树
  • 原文地址:https://www.cnblogs.com/mengxiangji/p/10834150.html
Copyright © 2011-2022 走看看