美文网首页Web前端之路让前端飞
ES6学习笔记——async 函数学习

ES6学习笔记——async 函数学习

作者: ac68882199a1 | 来源:发表于2017-06-04 22:04 被阅读10400次

    最近在使用 koa 框架的时候,发现中间件在使用 generator 时,控制台会抛出警告,提示在之后的 koa 版本中,将会移除对 generator 的支持,而改用 async

    最然在 koa2 中 generator 依然可用,但是强迫症真的不想在控制台看到这样的警告,于是就大致学习了一下 async 函数(注:async 函数是 ES2017 的标准)

    在跟作者一起学习 async 函数之前,小伙伴们可以先行看下下面的这三篇文章:

    看这一篇就够了!浅谈ES6的Promise对象
    Generator 函数语法
    Generator函数的异步用法

    什么是 async 函数

    async 函数算是一个语法糖,使异步函数、回调函数在语法上看上去更像同步函数

    async function asyncLoadData (urlOne, urlTwo) {
        let dataOne = await loadData (urlOne)
        let dataTwo = await loadData (urlTwo)
    }
    

    在上面的代码中,loadData方法是异步获取数据的方法

    可以看到,在 async 函数中,出现了一个陌生的关键字await——这个关键字只能够在 async 函数中使用,否则将会报错,它的意思是紧跟在其后面的表达式需要被等待执行结果

    小伙伴们有没有觉得上面的代码其实和 generator 函数有点类似呢?写成 generator 的话,应该是类似下面的函数:

    function * asyncLoadData (urlOne, urlTwo) {
        let dataOne = yield loadData (urlOne)
        let dataTwo = yield loadData (urlTwo)
    }
    

    但是 generator 与 async 的区别并不仅仅是将*改为async,将yield改为await

    generator 和 async 的区别

    内置执行器

    我们知道 generator 函数需要通过调用next()方法,才能往后执行到下一个yield,但是 async 函数却不需要,它能够自动向后执行

    更易理解

    如果你不曾了解过 generator 和 async 函数,那我想你一定无法直观的理解 generator,但是却可以轻易理解 async,这一点仅从字面意思就变现的很清楚了

    更适用

    yield命令后面只能跟随TrunkPromise,但是await后面除了可以是Promise,也可以是普通类型,但是这样就和同步没有任何区别了

    返回值

    generator 返回的是一个遍历器对象,而 async 返回的是一个 Promise 对象

    async 语法

    async 返回一个Promise,因此这个函数可以通过then添加回调函数,那么怎么向then中的回调添加参数呢?async 函数中 return 的结果将作为回调的参数

    async function test () {
        return 'this is a test async function'
    }
    
    test().then(
        resolveArg => console.log(resolveArg)
    )
    
    // 输出结果
    // this is a test async function
    

    同样,当 async 函数内部抛出一个错误时,也会被 catch 到,下面三种 catch 错误的方式都可以:

    async function errorTest () {
        throw new Error('this is an error');
    }
    
    // 在 then 的回调中捕获错误
    errorTest().then(
        resolve => console.log(resolve),
        error => console.log(error)
    )
    
    // 在 Promise 的 catch 方法中捕获
    errorTest().catch(
        error => console.log(error)
    )
    
    // 在 try...catch 语句中捕获
    try{
        errorTest()
    } catch (error) {
        console.log(error)
    }
    

    await 命令

    前面说了await命令后面可以是Promise也可以是普通数据类型,但如果是普通数据类型的话,会自动转换成状态为resolvePromise

    如果await后面的Promise状态转变成了reject,那么整个 async 函数都会停止执行,并且抛出相应的错误。即使这里没有return,也一样可以传入错误回调的参数

    所以当一个 async 函数中有多个 await命令时,如果不想因为一个出错而导致其与的都无法执行,应将await放在try...catch语句中执行

    async function testAwait () {
        try {
            await func1()
            await func2()
            await func3()
        } catch (error) {
            console.log(error)
        }
    }
    

    并发执行 await 命令

    当一个 async 函数中有多个await时,这些 await是继发执行的,只有当前一个await后面的方法执行完毕后,才会执行下一个

    如果我们前后的方法由依赖关系,继发执行是没有问题的,但是如果并没有任何关系的话,这样就会很耗时,所以需要让这些await命令同时执行,也就是并发执行

    // 方法 1
    let [res1, res2] = await Promise.all([func1(), func2()])
    
    // 方法 2
    let func1Promise = func1()
    let func2Promise = func2()
    let res1 = await func1Promise
    let res2 = await func2Promise
    

    async 函数的学习到这里就结束了,但是这并不意味着 async 的用法只有这些,我们在学习了基础以后,更要把它与其他的知识相结合起来,才能写出更可靠更优质的代码!

    如果你发现文中有任何错误的话,都欢迎指正,让我们一起学习进步!

    扫码关注前端周记公众号

    相关文章

      网友评论

        本文标题:ES6学习笔记——async 函数学习

        本文链接:https://www.haomeiwen.com/subject/tlybfxtx.html