Есть четыре решения проблемы обратного вызова ада:

Нет, нет! Есть ОДНО решение, и лучше сосредоточиться на нем, чем путать младших разработчиков с плохими вариантами.

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 до более специализированных шаблонов. Любой разработчик, не знающий, как избежать или избежать ада обратного вызова, должен сначала попробовать обещания в качестве решения. Это отправная точка по умолчанию.