Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

【译】JavaScript中的async/await #20

Open
reng99 opened this issue May 3, 2019 · 0 comments
Open

【译】JavaScript中的async/await #20

reng99 opened this issue May 3, 2019 · 0 comments
Labels
blog a single blog javascript javascript tag translation translate somehing

Comments

@reng99
Copy link
Owner

reng99 commented May 3, 2019

异步的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/

@reng99 reng99 added blog a single blog translation translate somehing javascript javascript tag labels May 3, 2019
reng99 added a commit that referenced this issue May 3, 2019
reng99 added a commit that referenced this issue May 3, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
blog a single blog javascript javascript tag translation translate somehing
Projects
None yet
Development

No branches or pull requests

1 participant