重构:从Promise到Async/Await

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

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

Async/Await真的比Promise好吗?

是的是的。前端

这些天,我大概重构了1000行代码,最大的感受是代码简洁了不少:java

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

下面,咱们能够经过一个很是简单的示例来体验一下Async/Await的酸爽:node

示例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极大地简化了代码,使得代码可读性提升了很是多。git

Async/Await真的替代了Promise?

是的是的。程序员

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

一方面,这里替代的是异步代码的编写方式,并不是彻底抛弃你们心爱的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了!

参考

关于Fundebug

Fundebug专一于JavaScript、微信小程序、微信小游戏、支付宝小程序、React Native、Node.js和Java实时BUG监控。 自从2016年双十一正式上线,Fundebug累计处理了7亿+错误事件,获得了Google、360、金山软件、百姓网等众多知名用户的承认。欢迎免费试用!

版权声明

转载时请注明做者Fundebug以及本文地址:
blog.fundebug.com/2017/12/13/…

相关文章
相关标签/搜索