Есть четыре решения проблемы обратного вызова ада:
Нет, нет! Есть ОДНО решение, и лучше сосредоточиться на нем, чем путать младших разработчиков с плохими вариантами.
tldr: ИСПОЛЬЗУЙТЕ ОБЕЩАНИЯ
Решение «Добавить комментарии»
Разъяснение кода с помощью комментариев - это всегда хорошо, особенно для сложных функций. Однако добавление комментариев к коду, который квалифицируется как «ад обратных вызовов», является просто оправданием того, что его не улучшают. Это НЕ «решение».
Ценность хорошего асинхронного кода выходит за рамки его понимания. Речь идет о том, чтобы сделать код более модульным и, таким образом, его легче поддерживать и расширять. . Комментарии этому не заменяют.
Решение «Меньшие функции»
Разбиение кода на более мелкие функции - хорошая практика, но также НЕ «решение» от ада обратного вызова.
В статье подразумевается, что «ад обратных вызовов» только о «вложенных функциях», что крайне неточно. Это всего лишь один сценарий, и не самый распространенный. Ад обратных вызовов - это передача обратных вызовов между несколькими функциями как способ обработки асинхронного потока. Добавление еще большего количества функций в существующий лабиринт обратных вызовов не решает этой основной проблемы.
В приведенном примере показано, как НЕ обрабатывать асинхронность:
const getBeef = nextStep => { const fridge = leftFright; const beef = getBeefFromFridge(fridge); nextStep(beef); };
Мало того, что обратный вызов nextStep
плохо пахнет, причина этой дополнительной функции неясна? fridge
'константа' не принадлежит к этой функции ; это сбивает с толку.
Кроме того, этот код выглядит ПОВРЕЖДЕННЫМ! Все остальные шаги являются асинхронными, поэтому мы должны предполагать, что getBeefFromFridge()
тоже. Однако эта функция вызывает getBeefFromFridge()
, а затем немедленно запускает обратный вызов nextStep()
с результатом. К сожалению, это похоже на ошибку! Эта дополнительная функция сделала код более понятным? Или он действительно что-то запутал, так что вы даже не заметили эту ошибку?
Этот надуманный пример показывает, как простое добавление дополнительных функций не делает код автоматически чище или понятнее.
Перемещение этого блока кода в функцию меньшего размера также ничего не помогло решить проблему ада обратного вызова. В любом случае это ухудшило ситуацию. Чем больше становится лабиринт обратных вызовов, тем глубже мы погружаемся в «ад» и тем труднее будет исправить позже.
"Promises" и "Async / Await"
Они представлены как 2 отдельных «решения»; они не! Это одно и то же . Async / await - это всего лишь синтаксический сахар для обещаний; не что иное, как личное предпочтение стиля кода. Лично я считаю, что синтаксис async / await чрезмерно используется, но это уже другая тема. ; )
В статье приводится достойный пример обещания «приготовить гамбургер». Однако он мог бы быть еще более кратким и действительно продемонстрировал силу обещаний. Например, приготовление говядины и приготовление булочки можно выполнять одновременно; это просто представить с помощью обещаний. Кроме того, мы можем показать, как ошибки также передаются обратно, автоматически…
const makeBurger = () => ( Promise.all([ getBeef().then(cookBeef), getBun().then(addCondiments) ]) .then(putBeefBetweenBuns); ); // Make and serve burger makeBurger() .then(serve) .catch(error => Print(`Unable to make your burger: ${error}`));
Ясное, краткое и мощное сочетание одновременных и последовательных асинхронных процессов. Попробуйте это с помощью обратных вызовов!
Замечательно также показать код, используя async / await sugar (как это сделал автор), но это все равно будет одно решение, а не два.
Создание дела
Я думаю, что автору следовало сосредоточиться на объяснении почему обещаний - лучшее решение и как их эффективно использовать. Это лучше достигло бы поставленной цели - помочь младшим разработчикам избежать " обратный вызов ад ».
Остается ли код в одной функции или разбит на множество подпрограмм, не имеет значения для фундаментальной проблемы обратных вызовов. Проблема в том, как обрабатывается асинхронный поток. Не имеет значения, между несколькими функциями или внутри одной функции.
Тема комментирования - это всего лишь часть создания самодокументируемого кода. Например, вы можете прокомментировать каждый .then()
блок в многоступенчатой функции ; или переместите блоки кода в подпрограммы с четко обозначенными именами, чтобы комментарии стали ненужными. Оба шаблона улучшают ясность кода, но ни один не является «решением» от ада обратного вызова.
Обещания, комментарии и разделение кода на более мелкие подпрограммы - все это часть написания хорошего кода, но ТОЛЬКО ОБЕЩАНИЯ - это решение для обратного вызова.
В другом комментарии упоминается паттерн наблюдателя. В этом есть свое применение, но каждый разработчик должен освоить promises до более специализированных шаблонов. Любой разработчик, не знающий, как избежать или избежать ада обратного вызова, должен сначала попробовать обещания в качестве решения. Это отправная точка по умолчанию.