JavaScript async и await

 Асинхронный JavaScript никогда не был легким. Некоторое время мы использовали обратные вызовы. Тогда мы использовали обещания. И теперь у нас есть асинхронные функции.

Асинхронные функции облегчают написание асинхронного JavaScript, но он поставляется со своим собственным набором gotchas, что делает жизнь трудной для начинающих.

В этой серии из 2 частей я хочу поделиться всем, что вам нужно знать об асинхронных функциях.

Асинхронные функции

Асинхронные функции содержат asyncключевое слово. Его можно использовать в обычном объявлении функции:

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

Вы также можете использовать его в функции стрелки.

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

Асинхронные функции всегда возвращают обещания

Это не имеет значения, что вы return. Возвращаемое значение всегда будет обещанием.

const getOne = async _ => { 
  return 1 
} 

const promise = getOne()
console.log(promise) // Promise 

Примечание: Вы должны знать, что такое обещания JavaScript и как их использовать, прежде чем двигаться дальше. В противном случае, это начнет запутываться. Эта статьяпоможет вам ознакомиться с обещаниями JavaScript.

Ключевое слово await

Когда вы вызываете обещание, вы обрабатываете следующий шаг в thenвызове, как это:

const getOne = async _ => { 
  return 1 
} 

getOne()
  .then(value => {
    console.log(value) // 1
  })

awaitКлючевое слово позволяет дождаться разрешения проблемы. После разрешения promise возвращает параметр, переданный в thenвызов.

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

test()

Возвращение жду

Там нет необходимостиawait, прежде чем вернуть обещание.Вы можете возвратить обещание сразу.

(Если вы return awaitчто-то, вы решить первоначальное обещание в первую очередь. Затем создайте новое обещание из разрешенного значения. 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, вам не нужно использовать асинхронную функцию. Приведенный выше пример можно переписать следующим образом:

// Do this instead
const test = _ => {
  return getOne()
}

test()
  .then(value => {
    console.log(value) // 1
  })

Обработка ошибок

Если обещание приводит к ошибке, вы обрабатываете его с помощью 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()

Есть лучший способ.

Мы знаем, что асинхронные функции всегда возвращают обещание. Когда мы вызываем обещание, мы можем обрабатывать ошибки в 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)))

Примечание: catchметод Promise позволяет поймать только одну ошибку.

Несколько ждет

await блокирует JavaScript от выполнения следующей строки кода, пока обещание не будет выполнено. Это может привести к непреднамеренному замедлению выполнения кода.

Чтобы показать это в действии, нам нужно создать задержку перед разрешением обещания. Мы можем создать задержку с sleepфункцией.

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

ms число миллисекунд ожидания перед разрешением. Если вы перейдете 1000вsleep, JavaScript будет ждать одну секунду, прежде чем решить обещание.

// Using Sleep
console.log('Now')
sleep(1000)
  .then(v => { 
    console.log('After one second') 
  })
Консоль немедленно регистрирует 'now'. Одна секунда спустя, он регистрирует "после одной секунды"

СкажемgetOne, требуется одна секунда, чтобы решить. Чтобы создать эту задержку, мы переходим 1000(одна секунда) в sleep. После того как одна секунда проходила и sleepобещание разрешает, мы возвращаем значение 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()
Консоль немедленно регистрирует 'Now'. Через одну секунду консольные журналы 1

Теперь предположим, что вам нужно дождаться трех обещаний. Каждое обещание имеет задержку в одну секунду.

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эти три обещания подряд, вам придется ждать в течение трех секунд, прежде чем все три обещания будут решены. Это не хорошо, потому что мы заставили 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()
Консоль немедленно показывает 'Now'. Через секунду он показывает 1. Еще через секунду, он показывает 2. Еще через секунду, он показывает 3 и "Сделано" в то же время.

Если getOnegetTwoи getThreeможет быть извлечена одновременно, вы сэкономите две секунды. Вы можете получить эти три обещания одновременно Promise.all.

Есть три шага:

  1. Создайте три обещания
  2. Добавьте все три обещания в массив
  3. await массив обещаний сPromise.all

Вот как это выглядит:

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()
Консоль немедленно показывает 'Now'. Через секунду консоль показывает 1, 2, 3 и "готово".

Это все, что вам нужно знать об основных асинхронных функциях! Я надеюсь, что эта статья прояснит для вас.

Примечание: эта статья представляет собой измененный отрывок из Learn JavaScript . Если вы нашли эту статью полезной, вы можете проверить ее.

Далее мы рассмотрим асинхронные функции и их поведение в циклах.

Спасибо за чтение. Эта статья помогла вам? Если это так, я надеюсь, что вы подумаете . Вы можете помочь кому-то другому. Большое спасибо!

Brain_Script
2802
2019-04-24 15:34:29
Нет комментариев
Яндекс.Метрика Яндекс.Метрика