Async/Await替代Promise的理由

Posted 45°微笑看世界

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Async/Await替代Promise的理由相关的知识,希望对你有一定的参考价值。

Async/Await简介

对于从未听说过async/await的朋友,下面是简介:

  • async/await是写异步代码的新方式,以前的方法有回调函数Promise
  • async/await是基于Promise实现的,它不能用于普通的回调函数。
  • async/await与Promise一样,是非阻塞的。
  • async/await使得异步代码看起来像同步代码,这正是它的魔力所在。

Async/Await语法

示例中,getJSON函数返回一个promise,这个promise成功resolve时会返回一个json对象。我们只是调用这个函数,打印返回的JSON对象,然后返回”done”。

使用Promise是这样的:

1 const makeRequest = () =>
2   getJSON()
3     .then(data => {
4       console.log(data)
5       return "done"
6     })
7 
8 makeRequest()

使用Async/Await是这样的:

1 const makeRequest = async () => {
2   console.log(await getJSON())
3   return "done"
4 }
5 
6 makeRequest()

为什么Async/Await更好?

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

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

示例1

 1 const Promise = require("bluebird")
 2 var readFile = Promise.promisify(require("fs").readFile)
 3  
 4 // 使用Promise
 5 function usePromise()
 6 {
 7     let a
 8     readFile("a.txt", "utf8")
 9         .then(tmp =>
10         {
11             a = tmp
12             return readFile("b.txt", "utf8")
13         })
14         .then(b =>
15         {
16             let result = a + b
17             console.log(result) // 输出"Hello, Fundebug!"
18         })
19  
20 }
21  
22 // 使用Async/Await
23 async function useAsyncAwait()
24 {
25     let a = await readFile("a.txt", "utf8")
26     let b = await readFile("b.txt", "utf8")
27     let result = a + b
28     console.log(result) // 输出"Hello, Fundebug!"
29 }
30  
31 usePromise()
32 useAsyncAwait()

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

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化,调用异步接口的时候有两种方式:

 1 const Promise = require("bluebird")
 2 var readFile = Promise.promisify(require("fs").readFile)
 3  
 4 // 使用Promise
 5 function usePromise()
 6 {
 7     readFile("b.txt", "utf8")
 8         .then(b =>
 9         {
10             console.log(b)
11         })
12 }
13  
14 // 使用Async/Await
15 async function useAsyncAwait()
16 {
17     var b = await readFile("b.txt", "utf8")
18     console.log(b) // 输出"Fundebug!"
19 }
20  
21 usePromise()
22 useAsyncAwait()

示例3:Promise.map

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

 1 const Promise = require("bluebird")
 2 var readFile = Promise.promisify(require("fs").readFile)
 3 var files = ["a.txt", "b.txt"]
 4  
 5 // 使用Promise
 6 function usePromise()
 7 {
 8     Promise.map(files, file =>
 9         {
10             return readFile(file, "utf8")
11         })
12         .then(results =>
13         {
14             console.log(results)
15         })
16 }
17  
18 // 使用Async/Await
19 async function useAsyncAwait()
20 {
21     var results = await Promise.map(files, file =>
22     {
23         return readFile(file, "utf8")
24     })
25     console.log(results)
26 }
27  
28 usePromise()
29 useAsyncAwait()

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

Async/Await有什么问题吗?

有啊有啊。

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

示例4

 1 const Promise = require("bluebird")
 2 var readFile = Promise.promisify(require("fs").readFile)
 3  
 4 // 没有Async
 5 function withoutAsync()
 6 {
 7     let b = await readFile("b.txt", "utf8") // 报错"SyntaxError: Unexpected identifier"
 8     console.log(b) 
 9 }
10  
11 // 没有await
12 async function withoutAwait()
13 {
14     let b = readFile("b.txt", "utf8")
15     console.log(b) // 打印"Promise..."
16 }
17  
18 withoutAsync()
19 withoutAwait()

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

总结

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

以上是关于Async/Await替代Promise的理由的主要内容,如果未能解决你的问题,请参考以下文章

Async/Await替代Promise的6个理由

Async/Await替代Promise的6个理由

重构:从Promise到Async/Await

js异步回调Async/Await与Promise区别

promise和async的区别

js异步回调Async/Await与Promise区别 新学习使用Async/Await