Почему [не] надо использовать async/await
Вы наверняка видели эту гифку. Она наглядно демонстрирует, как развивались подходы к работе с асинхронными данными.
К сожалению, здесь не показано самое главное — обработка ошибок. Ведь какой прок от нашего приложения, если один неудачный запрос ломает всю логику.
Вот как будет выглядеть код с обработкой ошибок на промисах:
А так на асинках:
С одной стороны, для работы асинков мы по-прежнему используем промисы, однако если в первом примере ошибка обработается методом catch
, то в асинках приходится использовать уже полноценный try catch
.
Более того, async
-функция сама возвращает промис, а значит, мы можем эвейтить и ее. По аналогии, вместоresolve
мы просто возвращаем значение, а вместо reject
— кидаем ошибку. Еще раз на примерах:
Теперь на асинках:
Код выполняется до момента, когда будет выброшена ошибка:
Обратите внимание, что теперь вы не сможете допустить классическую ошибку, когда then
будет вызван не только при успешном результате, но и после обработки методом catch
(для этого нужно поменять их местами или поставить колбек вторым аргументом then
).
Сложная логика, которая с промисами очень быстро превращается в спагетти, сохраняет читаемость гораздо дольше:
Также стоит отметить, что async/await
более лучше работает со стек-трейсом.
Разве что фетчи выглядят немного странно:
С другой стороны, посмотрите, как преображается thunk
в редуксе:
С параллельными запросами чуть сложнее — await
всегда выполняется последовательно, поэтому есть разные варианты, как обхитрить эту логику. Например, заранее создать промисы, а уже потом эвейтить внутри массива:
Или же воспользоваться старым-добрым Promise.all()
:
В обоих случаях результат будет получен после того, как отработают оба промиса. Либо с одной стороны промис, либо с другой. Более подробно можно почитать в этом треде на Stack Overflow.
Асинки уже доступны почти во всех браузерах (как обычно особняком стоит Internet Explorer).
Для компиляции совместимого кода используется фейсбучная библиотека regenerator. К примеру, на выходе asyncFnFail
превратится в такую портянку:
Ладно, с минификацией это выглядит не так страшно, но все равно стоит помнить что каждый async/await
увеличивает размер финального бандла.
Когда я только начинал писать эту статью, то скептически относился к асинкам (как и к любой другой модной штуковине). Сейчас, после того, как мы внедрили их почти на всех наших проектах, могу говорить с уверенностью : асинки действительно могут повысить читаемость кода, как при работе с последовательными вызовами, так в целом с запутанной логикой.
В общем, рекомендую.