как избежать антипаттерна явной конструкции обещаний в javascript

Аватар пользователя Elena Gromova
Elena Gromova
25 декабря 2024

Антипаттерн явной конструкции обещаний (называемый также "promise chaining") возникает, когда разработчики неправильно используют промисы в JavaScript, что приводит к сложным и нечитабельным цепочкам .then(). Это может произойти, когда структура кода становится слишком сложной и запутанной из-за множественных вложенных вызовов .then(), обработчиков ошибок и т.д. Вот как можно избежать этого антипаттерна:

1. Используйте async/await

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

Пример:

// Явная конструкция промисов
fetch('/api/data')
  .then(response => response.json())
  .then(data => {
    return fetch(`/api/other-data?id=${data.id}`);
  })
  .then(otherData => {
    console.log(otherData);
  })
  .catch(error => {
    console.error('Error:', error);
  });

// Использование async/await
async function fetchData() {
  try {
    const response = await fetch('/api/data');
    const data = await response.json();
    const otherResponse = await fetch(`/api/other-data?id=${data.id}`);
    const otherData = await otherResponse.json();

    console.log(otherData);
  } catch (error) {
    console.error('Error:', error);
  }
}

В примере с async/await код стал более понятным и простым для понимания.

2. Избегайте сложных вложенных .then()

Когда у вас возникает необходимость использовать несколько .then(), старайтесь избегать вложенности, разделяя логику на вспомогательные функции.

Пример:

function handleResponse(response) {
  // Обработка ответа
  return response.json();
}

function fetchOtherData(data) {
  return fetch(`/api/other-data?id=${data.id}`).then(handleResponse);
}

fetch('/api/data')
  .then(handleResponse)
  .then(fetchOtherData)
  .then(console.log)
  .catch(console.error);

3. Используйте обработчики ошибок на уровне метода

Вместо того чтобы добавлять .catch() после каждого .then(), добавьте его в конце всей цепочки. Это поможет избежать громоздкой обработки ошибок.

Пример:

fetch('/api/data')
  .then(handleResponse)
  .then(fetchOtherData)
  .then(console.log)
  .catch(error => {
    console.error('Error:', error);
  });

4. Промисы с использованием Promise.all

Когда у вас есть несколько независимых асинхронных операций, которые могут выполняться параллельно, используйте Promise.all, чтобы избежать ненужной вложенности.

Пример:

async function fetchData() {
  try {
    const responses = await Promise.all([
      fetch('/api/data'),
      fetch('/api/other-data')
    ]);
    const dataArray = await Promise.all(responses.map(response => response.json()));

    console.log(dataArray);
  } catch (error) {
    console.error('Error:', error);
  }
}

5. Модульность кода

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

Пример:

async function fetchData() {
  // Логика получения базовых данных
}

async function fetchOtherData(data) {
  // Логика получения других данных
}

async function main() {
  try {
    const data = await fetchData();
    const otherData = await fetchOtherData(data);
    console.log(otherData);
  } catch (error) {
    console.error('Error:', error);
  }
}

main();
0 0