[en] How to escape async/await hell. Надо ли с ним связываться?

Статья How to escape async/await hell

Года два-три назад нам начали рассказывать о callback hell в javascript. И как средство решения предлагали использовать promises. Потом пошла волна статей о том как ужасно если в promise не словить ошибку (благо хром выбрасывает ошибку в консоль), бонусом была несовместимость некоторых реализаций промисов: главное изменение jquery между версиями 2-3 было привнесение совместимости jquery промисов со стандартными промисами.

Потом предложили решить проблему множествнных вложенных вызовов через async/await - с их помощью можно писать как бы синхронный код, но который будет выполняться асинхронно (и с ограничениями по параллельности). И вот новая волна статей о том что ай-яй-яй есть проблемы и с этим подходом.

А умудренные опытом люди продолжали писать код на коллбеках (которые можно, хоть и с трудом, превратить в promise и async/await конструкцию).

Personally I use callbacks for 90% of the async code I write and when things get complicated I bring in something like run-parallel or run-series. I don’t think callbacks vs promises vs whatever else really make a difference for me, the biggest impact comes from keeping code simple, not nested and split up into small modules.

Это я к тому что чтобы начать решать задачи на javascript тебе не нужны promises или async/await. Коллбеки проще, не привносят новых сущностей и нового поведения и работают без дополнительных телодвижений (для async/await нужно транспайлить код).

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

3 лайка

Но хомячки с тобой несогласны. Даешь больше новых фигнюшек во славу бога всяких новых фигнюшек!

glory

Если серьезно, то это пожалуй один из самых важных советов – не бросаться на все подряд и всегда помнить о постоянно возрастающей энтропии системы при очередном усложнонении во имя упрощения.

А колбэки они разве не выполняются синхронно в JS типа:

foo = function(){..};
a = function(f){
.
f();
.
.
};
a(foo);

Вроде же a() не вернет результат пока foo() не выполнится, или я чет не так понял ?

В твоем примере все верно - функции выполняются синхронно. Коллбек - это функция, выполнение которой запланировано. Само выполнение будет синхронным, но вот когда оно начнется - это аспект асинхронности.

Пример когда выполнение коллбека main запланировано через 2 секунды. При этом код вне этого коллбека продолжит выполняться. Т.е. сначала в консоли увидишь ‘main planned’ а черезе примерно 2 секунды ‘main call’. Этот пример можно запустить в браузере.

function main() {
	console.log('main call')
}

setTimeout(main, 2000)
console.log('main planned')

С API которые доступаются к каким-то ресурсам (IO) принцип тот же. Например чтение файла. Поток выполнения js не останавливается пока система делает все телодвижения, которые нужны чтобы получить содержимое файла (это дорогая операция). Это значит что сначала в консоли появится ‘Started reading’, а через время, которое понадобилось системе чтобы вычитать файл, само содержимое файла.

Когда содержимое файла вычитано, js запустит (там есть целая история о тем как этот scheduler работает, спроси - кину ресурсов) функцию-коллбек, аргументом в которую передаст содержимое файла.

fs.readFile('/etc/hosts', 'utf-8' function (err, fileContents) {
	console.log(fileContents)
})
console.log('Started reading')

Но получается, что если функция обращается к внешнему ресурсу или ей поставлена задержка, то ее выполнение уходит в параллель с основным потоком выполнения, а если две функции, например вычисления, не зависят от внешнего ресурса, то они выполняются последовательно, даже если первая функция выполняется 5 секунд, а вторая 1 миллисекунду. И для контроля и синхронизации асинхронного выполнения мы используем callback функции, для построения жесткой цепочки выполнения, которая взаимодействует с внешними ресурсами?

Все валидно описал за мелким исключением:

В сам движок JS не встроено понятие паралельности. Есть понятия асинхронности - “выпадение” из основной последовательности выполнения. При этом асинхронная функция выполнится в том же потоке что и синхронная, просто в будущем.