美文网首页IT知识程序员程序园
【译】JavaScript中的async/await

【译】JavaScript中的async/await

作者: Ming_Hu | 来源:发表于2019-05-03 16:47 被阅读0次

    异步的JavaScript从未如何简单!过去段时间,我们使用回调。然后,我们使用promises。现在,我们有了异步功能函数。

    异步函数能够使得(我们)编写异步JavaScript更加容易,但是,它自带一套陷阱,对初学者很不友好。

    在这个由两部分组成的文章中,我想分享下你需要了解的有关异步函数的内容。【PS:另一部分暂不打算翻译】

    异步功能

    异步功能函数包含async关键词。你可以在正常的函数声明中使用它:

    async function functionName (arguments) {
      // Do something asynchronous
    }
    

    你也可以使用箭头函数。

    const functionName = async (arguments) => {
      // Do something asynchronous
    }
    

    异步函数总是返回promises

    (异步函数)它不管你返回什么。其返回值都是promise

    const getOne = async _ => { 
      return 1 
    } 
    
    const promise = getOne()
    console.log(promise) // Promise 
    

    笔记:在接着往前读之前,你应该知道什么是JavaScript Promises知识点,以及如何使用它们。否则,它会开始变得混乱。这篇文章会帮助你熟悉JavaScript Promise。

    await关键字

    当你调用promise时,你会在then中处理下一步,如下:

    const getOne = async _ => { 
      return 1 
    } 
    
    getOne()
      .then(value => {
        console.log(value) // 1
      })
    

    await关键字允许你等待promise去解析。一旦解析完promise,它就会返回参数传递给then调用。

    const test = async _ => {
      const one = await getOne()
      console.log(one) // 1
    }
    
    test()
    

    返回await

    在返回承诺(promise)之前没有必要等待(await)。你可以直接退回承诺。

    如果你return await些内容,则你首先是解决了原先promise。然后,你从已经解析的内容(resolved value)创建新的promise。return await真的没做什么有效的东西。无需额外的步骤。

    // Don't need to do this 
    const test = async _ => {
      return await getOne()
    }
    
    test()
      .then(value => {
        console.log(value) // 1
      })
    
    // Do this instead
    const test = async _ => {
      return getOne()
    }
    
    test()
      .then(value => {
        console.log(value) // 1
      })
    

    注意:如果你不需要await,则不需要使用异步功能(async function)。上面的例子可以改写如下:

    // Do this instead
    const test = _ => {
      return getOne()
    }
    
    test()
      .then(value => {
        console.log(value) // 1
      })
    

    处理错误

    如果一个promise出错了,你可以使用catch调用来处理它,如下所示:

    const getOne = async (success = true) => { 
      if (success) return 1
      throw new Error('Failure!')
    } 
    
    getOne(false)
      .catch(error => console.log(error)) // Failure!
    

    如果你想在一个异步函数中处理错误,你需要调用try/catch

    const test = async _ => {
      try {
        const one = await getOne(false)
      } catch (error) {
        console.log(error) // Failure!
      }
    }
    
    test()
    

    如果你有多个await关键字,错误处理可能变得很难看...

    const test = async _ => {
      try {
        const one = await getOne(false)
      } catch (error) {
        console.log(error) // Failure!
      }
    
      try {
        const two = await getTwo(false)
      } catch (error) {
        console.log(error) // Failure!
      }
    
      try {
        const three = await getThree(false)
      } catch (error) {
        console.log(error) // Failure!
      }
    }
    
    test()
    

    还有更好的方法。

    我们知道异步函数总是返回一个promise。当我们调用promise时,我们可以在catch调用中处理错误。这意味着我们可以通过添加.catch来处理异步函数中的任何错误。

    const test = async _ => {
      const one = await getOne(false)
      const two = await getTwo(false)
      const three = await getThree(false)
    }
    
    test()
      .catch(error => console.log(error)))
    

    注意:Promise的catch方法只允许你捕获一个错误。

    多个awaits

    await阻止JavaScript执行下一行代码,直到promise解析为止。这可能会导致代码执行速度减慢的意外效果。

    为了实际演示这点,我们需要在解析promise之前创建一个延迟。我们可以使用sleep功能来创建延迟。

    const sleep = ms => {
      return new Promise(resolve => setTimeout(resolve, ms))
    }
    

    ms是解析前等待的毫秒数。如果你传入1000sleep函数,JavaScript将等待一秒才能解析promise。

    // Using Sleep
    console.log('Now')
    sleep(1000)
      .then(v => { 
        console.log('After one second') 
      })
    
    sleep

    假设getOne需要一秒来解析。为了创建这个延迟,我们将1000(一秒)传入到sleep。一秒过后,sleeppromise解析后,我们返回值1。

    const getOne = _ => {
      return sleep(1000).then(v => 1)
    }
    

    如果你使用await getOne(),你会发现在getOne解析之前需要一秒钟。

    const test = async _ => {
      console.log('Now')
    
      const one = await getOne()
      console.log(one)
    }
    
    test()
    
    block-1

    现在,假设你需要处理三个promises。每个promise都有一秒钟的延迟。

    const getOne = _ => {
      return sleep(1000).then(v => 1)
    }
    
    const getTwo = _ => {
      return sleep(1000).then(v => 2)
    }
    
    const getThree = _ => {
      return sleep(1000).then(v => 3)
    }
    

    如果你连续await这三个promises,你将要等待三秒才能解析完所有promises。这并不好,因为我们强迫JavaScript在做我们需要做的事情之前等待了两秒钟。

    const test = async _ => {
      const one = await getOne()
      console.log(one)
    
      const two = await getTwo()
      console.log(two)
    
      const three = await getThree()
      console.log(three)
    
      console.log('Done')
    }
    
    test()
    
    block-2

    如果getOnegetTwogetThree可以同时获取,你将节省两秒钟。你可以使用Promise.all同时获取这三个promises。

    有三个步骤:

    1. 创建三个promises
    2. 将三个promises添加到一个数组中
    3. 使用Promise.allawaitpromises数组

    如下所示:

    const test = async _ => {
      const promises = [getOne(), getTwo(), getThree()]
      console.log('Now')
    
      const [one, two, three] = await Promise.all(promises)
      console.log(one)
      console.log(two)
      console.log(three)
    
      console.log('Done')
    }
    
    test()
    
    block-3

    这就是你需要了解的基本异步功能函数!我希望这篇文章为你扫除了些障碍。

    笔记:这篇文章是Learn JavaScript的修改摘录。如果你发现本文有用,你可能需要去查看它。

    后话

    原文:https://zellwk.com/blog/async-await/

    文章首发:https://github.com/reng99/blogs/issues/20

    同步掘金:https://juejin.im/post/5ccbbf6ce51d453a59418b68

    至此,系列文callbacks,promisesasync/await共三篇文章已经完成~

    更多内容:https://github.com/reng99/blogs/

    相关文章

      网友评论

        本文标题:【译】JavaScript中的async/await

        本文链接:https://www.haomeiwen.com/subject/hdlznqtx.html