ES2025: Promise.try — Унифицированная обработка ошибок

Источник: «Promise.try: Unified Error Handling for Sync and Async JavaScript Code (ES2025)»
Прекратите смешивать try/catch с цепочками промисов — новый Promise.try в JavaScript обрабатывает возвращаемые значения, промисы и ошибки унифицировано

В JavaScript появилась новая утилита промиса, позволяющая сделать работу с потенциально асинхронными функциями чище и безопаснее. Promise.try позволяет обернуть любую функцию в промис, независимо от того, асинхронная она или нет, сохраняя оптимальное время выполнения.

Суть проблемы

Работа с функциями, которые могут быть синхронными или асинхронными, требует смешивания различных шаблонов обработки ошибок:

function getUserData(id) {
// Нам нужны try/catch для синхронных ошибок
try {
validateId(id);

// Может возвращать кэшированные данные синхронно
if (id in cache) {
return cache[id];
}

// Может вернуть промис
return fetch(`/api/users/${id}`);
} catch (syncError) {
handleSyncError(syncError);
}
}

Проблема? Вы не знаете, какое поведение получите. Сейчас существует два распространённых способа решения этой проблемы, и оба не идеальны:

// Метод 1: Использование Promise.resolve().then()
Promise.resolve().then(() => getUserData(123));
// ❌ Заставляет всё работать в асинхронно
// ❌ Даже кэшированные данные ждут следующего тика.
// ✔️ Но, по крайней мере, ловит ошибки.

// Метод 2: Использование new Promise
new Promise(resolve => resolve(getUserData(123)));
// ❌ Многословный и неуклюжий
// ❌ Легко ошибиться
// ✔️ Синхронный код выполняется немедленно

Нам нужен лучший способ:

Решение: Promise.try

Promise.try предоставляет единый чистый способ обработки всех случаев:

// Чистый, безопасный и оптимальный тайминг
Promise.try(() => getUserData(123))
.then(user => {
// Вызывается с:
// - Немедленные значения (из кэша)
// - Решённые значения Promise (из fetch)
})
.catch(error => {
// Ловит оба:
// - Синхронные исключения
// - Отклонённые промисы
});

Чем Promise.try лучше

Promise.try имеет три ключевых преимущества:

  1. Выполняется синхронно, когда это возможно
  2. Надёжно отлавливает все ошибки
  3. Обрабатывает синхронные и асинхронные задачи естественно
// 1. Выполняется синхронно, когда это возможно
Promise.try(() => "instant") // Выполняется немедленно
.then(x => console.log(x));

// 2. Надёжно отлавливает все ошибки
Promise.try(() => {
throw new Error('boom');
})
.catch(err => console.log('Caught:', err));

// 3. Обрабатывает синхронные и асинхронные задачи естественно
Promise.try(() => {
if (Math.random() > 0.5) {
return "sync value";
}
return fetch('/api/data');
});

Promise.try немедленно запускает синхронный код для повышения производительности, но при этом при необходимости выполняет асинхронные операции. Отлавливает все типы ошибок с помощью одного обработчика catch и делает это с помощью чистого, удобного для чтения синтаксиса. Думайте об этом как об эквиваленте блока try-catch в Promise — безопасном способе выполнения кода, который может быть неудачным или асинхронным, без необходимости заранее знать, что это такое.

Это позволяет работать с функциями, изменяющими своё поведение с течением времени. Обработка ошибок остаётся неизменной независимо от того, завершается функция сразу или нужно сделать вызов API. Не нужно заворачивать всё в блоки try-catch, а затем отдельно обрабатывать отклонённые Promise.

Справочная информация

Комментарии


Дополнительные материалы

Предыдущая Статья

Новые возможности CSS за 2024 год

Следующая Статья

Настройка .htaccess для безопасности и производительности Apache