资讯专栏INFORMATION COLUMN

重构:从Promise到Async/Await

zhangfaliang / 985人阅读

摘要:一方面,这里替代的是异步代码的编写方式,并非完全抛弃大家心爱的,地球人都知道是基于的,不用太伤心另一方面,是基于回调函数实现的,那也没有替代回调函数咯重构代码之后,我仍然用到了库。

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

GitHub仓库: Fundebug/promise-asyncawait

早在半年多之前,我就在鼓吹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了!

参考

Async/Await替代Promise的6个理由

Async/Await是这样简化JavaScript代码的

版权声明:
转载时请注明作者Fundebug以及本文地址:
https://blog.fundebug.com/2017/12/13/reconstruct-from-promise-to-async-await/

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/92443.html

相关文章

  • async语法升级踩坑小记

    摘要:普通的回调函数调用执行后续逻辑使用了以后的复杂逻辑获取到正确的结果输出两个文件拼接后的内容虽说解决了的问题,不会出现一个函数前边有二三十个空格的缩进。所以直接使用关键字替换原有的普通回调函数即可。 从今年过完年回来,三月份开始,就一直在做重构相关的事情。 就在今天刚刚上线了最新一次的重构代码,希望高峰期安好,接近半年的Node.js代码重构。 包含从callback+async.w...

    VioletJack 评论0 收藏0
  • 一个真实的Async/Await示例

    摘要:如果不希望定义多余的外层变量,则需要在链中的每一个函数中都返回变量,这样做显然更加糟糕。 译者按: 通过真实的代码示例感受Async/Await的力量。 原文: Async/await - A thorough example 译者: Fundebug 为了保证可读性,本文采用意译而非直译。另外,本文版权归原作者所有,翻译仅用于学习。 既然Node.js 8已经LTS了,我想大...

    habren 评论0 收藏0
  • Fluent Fetcher: 重构基于 Fetch 的 JavaScript 网络请求库

    摘要:重构基于的网络请求库从属于笔者的开发基础与工程实践系列文章与项目,记述了笔者对内部使用的封装库的设计重构与实现过程。基本使用版本中的中,最核心的设计变化在于将请求构建与请求执行剥离了开来。而函数则负责执行请求,并且返回经过扩展的对象。 Fluent Fetcher: 重构基于 Fetch 的 JavaScript 网络请求库从属于笔者的 Web 开发基础与工程实践系列文章与项目,记述了...

    Yangder 评论0 收藏0
  • js的异步回调之async/await

    摘要:假如返回的不是一个对象,是其他的任何返回值,后面的语句会立即执行。而关键字只有得到返回值后才继续执行,不就是同步么。 最近在学习NodeJS框架koa V2,koa2的API很简单,基于ES7 async/await实现异步代码。很多人认为async/await是解决异步终极解决方案,那我们就研究下async/await。前端业务逻辑越来越复杂,往往几个 AJAX 请求之间互有依赖,有...

    vspiders 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<