«Если рабочий хочет хорошо выполнять свою работу, он должен сначала заточить свои инструменты» — Конфуций, «Аналитики Конфуция. Лу Лингун»
титульная страница > программирование > Понимание ада обратных вызовов: проблема, решения и примеры кода

Понимание ада обратных вызовов: проблема, решения и примеры кода

Опубликовано 8 ноября 2024 г.
Просматривать:154

Understanding Callback Hell: The Problem, Solutions and Code Examples

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

Введение

Асинхронное программирование имеет решающее значение в современной разработке JavaScript, поскольку оно обеспечивает неблокирующее выполнение и повышает производительность, особенно для операций ввода-вывода. Однако это удобство иногда может привести к состоянию, печально известному как «ад обратных вызовов».

В этой статье мы углубимся в:

  1. Что такое ад обратного вызова и как он возникает.
  2. Проблемы, которые это создает.
  3. Решения, включая использование Promises и async/await.
  4. Примеры кода, чтобы все было понятно.

Что такое ад обратного вызова?

Ад обратного вызова, часто называемый «Пирамидой гибели», возникает, когда несколько вложенных асинхронных операций зависят друг от друга для последовательного выполнения. Этот сценарий приводит к запутанной путанице глубоко вложенных обратных вызовов, что затрудняет чтение, поддержку и отладку кода.

Пример ада обратного вызова:

getData(function(data) {
  processData(data, function(processedData) {
    saveData(processedData, function(response) {
      sendNotification(response, function(notificationResult) {
        console.log("All done!");
      });
    });
  });
});

Приведенный выше код последовательно выполняет несколько асинхронных операций. Хотя он работает, он быстро становится неуправляемым, если добавляется больше задач, что затрудняет понимание и поддержку. Вложенная структура напоминает пирамиду, отсюда и термин «Пирамида Судьбы».

Проблема с адом обратных вызовов

Ад обратного вызова приводит к нескольким проблемам:

  1. Сложно поддерживать: глубоко вложенный код сложно модифицировать/расширять. Вы можете внести ошибки, просто пытаясь добавить новую функциональность.
  2. Обработка ошибок: правильная обработка ошибок на разных вложенных уровнях становится сложной. Вам приходится обрабатывать ошибки для каждого отдельного обратного вызова, что может привести к повторению кода.
  3. Читаемость кода: понимание потока выполнения становится сложной задачей, особенно для разработчиков, незнакомых с кодовой базой.
  4. Масштабируемость: по мере роста количества вложенных обратных вызовов растет и сложность, что делает код немасштабируемым и трудным для отладки.

Обещания: решение проблемы ада обратных вызовов

Чтобы смягчить проблемы ада обратных вызовов, в JavaScript используются обещания. Промисы представляют собой возможное завершение (или сбой) асинхронной операции и позволяют писать чистый, более управляемый код. Обещания упрощают код - С помощью обещаний вложенная структура становится более плоской, а обработка ошибок становится более централизованной, что упрощает чтение и поддержку кода.

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

getData()
 .then(data => processData(data))
 .then(processedData => saveData(processedData))
 .then(response => sendNotification(response))
 .then(notificationResult => {
 console.log("All done!");
 })
 .catch(error => {
 console.error("An error occurred:", error);
 });

Этот подход исключает глубоко вложенные обратные вызовы. Каждый блок «то» представляет собой следующий шаг в цепочке, что делает процесс более линейным и простым для отслеживания. Обработка ошибок также централизована в блоке catch.

Как работают обещания

Промисы имеют три возможных состояния:

  1. Ожидание: исходное состояние, означающее, что обещание еще не выполнено или не отклонено.
  2. Выполнено: асинхронная операция успешно завершена.
  3. Отклонено: операция не удалась.

Объект Promise предоставляет методы '.then()' и '.catch()' для обработки сценариев успеха и неудачи.

function getData() {
 return new Promise((resolve, reject) => {
 // Simulating an async operation (e.g., API call)
 setTimeout(() => {
 const data = "Sample Data";
 resolve(data);
 }, 1000);
 });
}
getData()
 .then(data => {
 console.log("Data received:", data);
 })
 .catch(error => {
 console.error("Error fetching data:", error);
 });

В приведенном выше коде функция getData() возвращает обещание. Если асинхронная операция успешна, обещание выполняется с данными, в противном случае оно отклоняется с ошибкой.

Объединение обещаний

Одним из главных преимуществ промисов является то, что их можно объединять в цепочки. Это позволяет упорядочивать асинхронные операции без вложения.

function fetchData() {
 return new Promise((resolve, reject) => {
 setTimeout(() => resolve("Data fetched"), 1000);
 });
}
function processData(data) {
 return new Promise((resolve, reject) => {
 setTimeout(() => resolve(`${data} and processed`), 1000);
 });
}
function saveData(data) {
 return new Promise((resolve, reject) => {
 setTimeout(() => resolve(`${data} and saved`), 1000);
 });
}
fetchData()
 .then(data => processData(data))
 .then(processedData => saveData(processedData))
 .then(result => {
 console.log(result); 
// Output => Data fetched and processed and saved
 })
 .catch(error => console.error("Error:", error));

Благодаря объединению промисов код становится плоским, более читаемым и простым в обслуживании.

Async/Await: еще лучшая альтернатива

Хотя промисы являются значительным улучшением по сравнению с обратными вызовами, они все равно могут стать громоздкими из-за обширных цепочек. Здесь в игру вступает async/await.
Синтаксис Async/await позволяет нам писать асинхронный код, напоминающий синхронный код. Это делает ваш код чище и упрощает его анализ.

Использование Async/Await:

async function performOperations() {
  try {
    const data = await getData();
    const processedData = await processData(data);
    const response = await saveData(processedData);
    const notificationResult = await sendNotification(response);

    console.log("All done!");
  } catch (error) {
    console.error("Error:", error);
  }
}

performOperations();

В приведенном выше коде:

  • Ключевое слово async используется для определения асинхронной функции.
  • 'await' приостанавливает выполнение функции до тех пор, пока обещание не будет разрешено или отклонено, благодаря чему код выглядит синхронным.
  • Обработка ошибок намного проще: используется один блок try-catch.
  • Async/await устраняет ад обратных вызовов и длинные цепочки обещаний, что делает его предпочтительным способом обработки асинхронных операций в современном JavaScript.

Заключение

Ад обратного вызова — это распространенная проблема в JavaScript, которая возникает при работе с несколькими асинхронными операциями. Глубоко вложенные обратные вызовы приводят к созданию неподдерживаемого и подверженного ошибкам кода. Однако с появлением Promises и async/await у разработчиков появилась возможность писать более чистый, управляемый и масштабируемый код.

Promises сглаживают вложенные обратные вызовы и централизуют обработку ошибок, а async/await еще больше упрощает асинхронную логику, делая ее синхронной. Оба метода устраняют хаос ада обратных вызовов и гарантируют, что ваш код останется читаемым, даже если он становится сложнее.

Объявления в социальных сетях
Если эта статья оказалась для вас полезной, свяжитесь со мной в моих социальных сетях, чтобы получить дополнительную информацию:

  • GitHub: [AmanjotSingh0908]
  • LinkedIn: [Аманджот Сингх Сайни]
  • Твиттер: [@AmanjotSingh]

Спасибо, что прочитали!

Заявление о выпуске Эта статья воспроизведена по адресу: https://dev.to/amanjotsingh/understanding-callback-hell-the-problem-solutions-and-code-examples-3loh?1 Если есть какие-либо нарушения, пожалуйста, свяжитесь с [email protected] удалить его
Последний учебник Более>

Изучайте китайский

Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.

Copyright© 2022 湘ICP备2022001581号-3