zoukankan      html  css  js  c++  java
  • 重构:从Promise到Async/Await

     

    摘要: 夸张点说,技术的发展与历史一样,顺之者昌,逆之者亡。JS开发者们,赶紧拥抱Async/Await吧!

    早在半年多之前,我就在鼓吹Async/Await替代Promise的6个理由,似乎还招致了一些批评。然而,直到最近,我才真正开始进行代码重构,抛弃Promise,全面使用Async/Await。因为,Node 8终于LTS了

    Async/Await真的比Promise好吗?

    是的是的。

    这些天,我大概重构了1000行代码,最大的感觉是代码简洁了很多:

    • 真正地用同步的方式写异步代码
    • 不用写then及其回调函数,减少代码行数,也避免了代码嵌套
    • 所有异步调用可以写在同一个代码块中,无需定义多余的中间变量
    • async函数会隐式地返回一个Promise,因此可以直接return变量,无需使用Promise.resolve进行转换

    下面,我们可以通过一个非常简单的示例来体验一下Async/Await的酸爽:

    示例1

    const Promise = require("bluebird")
    var readFile = Promise.promisify(require("fs").readFile)

    // 使用Promise
    function usePromise()
    {
    let a
    readFile("a.txt", "utf8")
    .then(tmp =>
    {
    a = tmp
    return readFile("b.txt", "utf8")
    })
    .then(b =>
    {
    let result = a + b
    console.log(result) // 输出"Hello, Fundebug!"
    })

    }

    // 使用Async/Await
    async function useAsyncAwait()
    {
    let a = await readFile("a.txt", "utf8")
    let b = await readFile("b.txt", "utf8")
    let result = a + b
    console.log(result) // 输出"Hello, Fundebug!"
    }

    usePromise()
    useAsyncAwait()

    由示例可知,使用Async/Await极大地简化了代码,使得代码可读性提高了非常多。

    Async/Await真的替代了Promise?

    是的是的。

    对于Async/Await替代Promise的6个理由,批评者执着于Async/Await是基于Promise实现的,因此替代这个词不准确,这就有点尴尬了。

    一方面,这里替代的是异步代码的编写方式,并非完全抛弃大家心爱的Promise,地球人都知道Async/Await是基于Promise的,不用太伤心;另一方面,Promise是基于回调函数实现的,那Promise也没有替代回调函数咯?

    重构代码之后,我仍然用到了Promise库bluebird。”Talk is cheap, Show me the code!”,大家不妨看看两个示例。

    示例2:Promise.promisify

    使用Promise.promisify将不支持Promise的方法Promise化,调用异步接口的时候有两种方式:

    const Promise = require("bluebird")
    var readFile = Promise.promisify(require("fs").readFile)

    // 使用Promise
    function usePromise()
    {
    readFile("b.txt", "utf8")
    .then(b =>
    {
    console.log(b)
    })
    }

    // 使用Async/Await
    async function useAsyncAwait()
    {
    var b = await readFile("b.txt", "utf8")
    console.log(b) // 输出"Fundebug!"
    }

    usePromise()
    useAsyncAwait()

    Fundebug是全栈JavaScript错误监控平台,支持各种前端和后端框架,可以帮助您第一时间发现BUG!

    示例3:Promise.map

    使用Promise.map读取多个文件的数据,调用异步接口的时候有两种方式:

    const Promise = require("bluebird")
    var readFile = Promise.promisify(require("fs").readFile)
    var files = ["a.txt", "b.txt"]

    // 使用Promise
    function usePromise()
    {
    Promise.map(files, file =>
    {
    return readFile(file, "utf8")
    })
    .then(results =>
    {
    console.log(results)
    })
    }

    // 使用Async/Await
    async function useAsyncAwait()
    {
    var results = await Promise.map(files, file =>
    {
    return readFile(file, "utf8")
    })
    console.log(results)
    }

    usePromise()
    useAsyncAwait()

    没错,我的确使用了Promise库,readFile与Promise.map都是Promise函数。但是,在调用readFile与Promise.map函数时,使用Async/Await与使用Promise是两种不同写法,它们是相互替代的关系。

    Async/Await有什么问题吗?

    有啊有啊。

    使用了await的函数定义时要加一个async,调用异步函数的时候需要加一个await,这玩意写多了也觉着烦,有时候还容易忘掉。不写async代码直接报错,不写await代码执行会出错。

    示例4

    const Promise = require("bluebird")
    var readFile = Promise.promisify(require("fs").readFile)

    // 没有Async
    function withoutAsync()
    {
    let b = await readFile("b.txt", "utf8") // 报错"SyntaxError: Unexpected identifier"
    console.log(b)
    }

    // 没有await
    async function withoutAwait()
    {
    let b = readFile("b.txt", "utf8")
    console.log(b) // 打印"Promise..."
    }

    withoutAsync()
    withoutAwait()

    既然Async/Await写着有点添乱,可不可以不写呢?我想以后应该是可以的,只要能够自动识别异步代码就行了,这应该也是未来的发展方向。至于说如何实现,那我就不知道了哎。

    总结

    JavaScript的异步编写方式,从回调函数到Promise再到Async/Await,表面上只是写法的变化,本质上则是语言层的一次次抽象,让我们可以用更简单的方式实现同样的功能,而程序员不需要去考虑代码是如何执行的。在我看来,这样的进步应该不会停止,有一天我们也许不用写Async/Await了!

    参考



  • 相关阅读:
    Validation failed for one or more entities. See 'EntityValidationErrors' property for more details
    Visual Studio断点调试, 无法监视变量, 提示无法计算表达式
    ASP.NET MVC中MaxLength特性设置无效
    项目从.NET 4.5迁移到.NET 4.0遇到的问题
    发布网站时应该把debug设置false
    什么时候用var关键字
    扩展方法略好于帮助方法
    在基类构造器中调用虚方法需谨慎
    ASP.NET MVC中商品模块小样
    ASP.NET MVC中实现属性和属性值的组合,即笛卡尔乘积02, 在界面实现
  • 原文地址:https://www.cnblogs.com/fundebug/p/8353036.html
Copyright © 2011-2022 走看看