как избежать антипаттерна явной конструкции обещаний в javascript
Антипаттерн явной конструкции обещаний (называемый также "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();