Почему [не] надо использовать async/await

Вы наверняка видели эту гифку. Она наглядно демонстрирует, как развивались подходы к работе с асинхронными данными.

Обратите внимание, что с async/await кода становится больше. Мы еще вернемся к нему.

К сожалению, здесь не показано самое главное — обработка ошибок. Ведь какой прок от нашего приложения, если один неудачный запрос ломает всю логику.

Вот как будет выглядеть код с обработкой ошибок на промисах:

А так на асинках:

Мы не можем делать await сразу из корня, он всегда должен быть обернут в async.

С одной стороны, для работы асинков мы по-прежнему используем промисы, однако если в первом примере ошибка обработается методом catch, то в асинках приходится использовать уже полноценный try catch.

Более того, async-функция сама возвращает промис, а значит, мы можем эвейтить и ее. По аналогии, вместоresolve мы просто возвращаем значение, а вместо reject — кидаем ошибку. Еще раз на примерах:

Теперь на асинках:

Код выполняется до момента, когда будет выброшена ошибка:

Обратите внимание, что теперь вы не сможете допустить классическую ошибку, когда then будет вызван не только при успешном результате, но и после обработки методом catch (для этого нужно поменять их местами или поставить колбек вторым аргументом then).

Сложная логика, которая с промисами очень быстро превращается в спагетти, сохраняет читаемость гораздо дольше:

Я не буду приводить здесь пример на промисах. Вы можете попытаться реализовать его сами и посмотреть, что получится.

Также стоит отметить, что async/await более лучше работает со стек-трейсом.

Разве что фетчи выглядят немного странно:

С другой стороны, посмотрите, как преображается thunk в редуксе:

С параллельными запросами чуть сложнее — await всегда выполняется последовательно, поэтому есть разные варианты, как обхитрить эту логику. Например, заранее создать промисы, а уже потом эвейтить внутри массива:

Или же воспользоваться старым-добрым Promise.all():

Я буду эвейтить все функции!

В обоих случаях результат будет получен после того, как отработают оба промиса. Либо с одной стороны промис, либо с другой. Более подробно можно почитать в этом треде на Stack Overflow.


Асинки уже доступны почти во всех браузерах (как обычно особняком стоит Internet Explorer).

Две последние версии, Карл!

Для компиляции совместимого кода используется фейсбучная библиотека regenerator. К примеру, на выходе asyncFnFail превратится в такую портянку:

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


Когда я только начинал писать эту статью, то скептически относился к асинкам (как и к любой другой модной штуковине). Сейчас, после того, как мы внедрили их почти на всех наших проектах, могу говорить с уверенностью : асинки действительно могут повысить читаемость кода, как при работе с последовательными вызовами, так в целом с запутанной логикой.

В общем, рекомендую.