zoukankan      html  css  js  c++  java
  • 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了!

  • 相关阅读:
    bootstrap table中显示头行结构
    利用bootstrap的modal和tab制作的联动自定义UI
    oracle plsql练习题-考核题
    oracle pl/sql 几道基础的编程题
    洛谷 P1156 垃圾陷阱
    洛谷 3373 线段树练习
    JZOJ 5842
    JZOJ 5849 d
    JZOJ 4735. 最小圈
    JZOJ 4742. 单峰
  • 原文地址:https://www.cnblogs.com/shiweida/p/8763123.html
Copyright © 2011-2022 走看看