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了!
原文地址:https://www.cnblogs.com/shiweida/p/8763123.html