Что такое концепция?

Вы когда-нибудь просыпались поздно на работу или в школу, заставляя вас принять душ всего за 4 минуты? Если вы похожи на меня, то ответ «да — часто». Со временем, в попытке максимизировать эффективность, я научился принимать душ с нанесения шампуня, затем мыть тело, пока шампунь остается на волосах, и, наконец, споласкивать его. Это отличный пример выполнения набора задач асинхронно. Вместо того, чтобы ждать и ничего не делать, пока шампунь был на моих волосах, я поняла, что был период, когда мои волосы не нуждались в моем внимании. Затем я использовал эти знания, выполняя другие задачи в промежутке. В этом суть асинхронного программирования.

Как это перевести в код?

Решения для парадигмы

Слово асинхронный означает не существующее или происходящее одновременно. Многие языки программирования имеют либо встроенные функции, либо внешние библиотеки для реализации этой парадигмы. В этой статье я буду использовать JavaScript (ES6), так как он имеет простую встроенную реализацию асинхронности. Другие популярные решения включают библиотеку Python asyncio, библиотеку C++ std::async и библиотеку PHP Async.

Причины парадигмы

Теперь, когда вы знаете, что это за концепция и какие языки предлагают для ее реализации, вам, вероятно, интересно, какие проблемы она решает. Наиболее распространенные приложения для асинхронного программирования попадают под зонтик веб-разработки. Вызовы API, веб-перехватчики, веб-сокеты и связь между серверной частью и интерфейсом веб-приложений — все они так или иначе используют асинхронное программирование. Предположим, вы хотите создать веб-сайт, который отображает данные, предоставляемые Genius’ Lyrics API, для категоризации или доступа к текстам песен. Для этого вам нужно будет отправить API запрос (что-то сказать ему Я хочу текст для этой песни). Когда вы это сделаете, API вернет ответ, но это произойдет не мгновенно. Это может занять 0,01 секунды или 1 секунду. В зависимости от API это может занять даже 1 минуту. Вы не хотите, чтобы ваш веб-сайт полностью останавливался на все это время всякий раз, когда вы запрашиваете текст, поэтому реализация асинхронного программирования позволяет вашему коду продолжать работать, пока он ждет!

Пример кода

Допустим, вы хотите показать своим друзьям забавные факты о кошках, используя javascript и API фактов о кошках. Вы можете попытаться сделать это синхронно, используя Node.js, например:

const fetch = require(‘node-fetch’)
const result = fetch(‘https://cat-fact.herokuapp.com/facts/random')
console.log(result)

Но если вы сделаете это, результатом будет Promise { <pending> }, что не очень полезно. Есть два возможных решения этой проблемы, в зависимости от ваших предпочтений.

Использование промисов

Если мы хотим, чтобы наш результат действительно содержал факт о кошке, мы можем рассматривать его как объект Promise и использовать функцию .then() следующим образом:

const fetch = require('node-fetch')
const result = fetch(
'https://cat-fact.herokuapp.com/facts/random'
).then(
  (json) => {
    return json
  }
)

Это зарегистрирует наши фактические данные API, а не ожидающее обещание, которое мы получили ранее. Что делает .then():

  • Возьмите функцию обратного вызова, чтобы выполнить ее позже
  • подождите, пока промис перестанет быть "ожидающим", а будет "решенным", а затем выполните функцию обратного вызова с этим разрешенным значением.

Это чисто решает нашу проблему и легко расширяемо, но, возможно, это не самый красивый код. На мой взгляд, решение async/await более интуитивно понятно и визуально привлекательно.

Асинхронно/ждите

Чтобы добиться того же результата, что и наше решение с промисами, но с использованием функций async/await ES6, мы можем использовать следующее:

const fetch = require('node-fetch')
const awaitResponse = async () => {
  const response = await fetch(
    'https://cat-fact.herokuapp.com/facts/random'
  )
  const data = await response.json()
  console.log(data)
}
awaitResponse()

Это работает так же, как и наше решение promises, но больше не использует .then(). Что мы делаем здесь:

  • Определите асинхронную функцию, используя ключевое слово async
  • Внутри этой функции мы await вызываем асинхронный API, который буквально ждет, пока не разрешится, прежде чем продолжить.
  • Мы снова используем await, чтобы получить данные JSON, сохраненные в результате нашего вызова API.
  • Затем мы записываем данные JSON в консоль.