> Можно ли создать функцию для запроса продуктов, которая возвращает промис (JavaScript)

Уровень: senior · Роль: frontend · Категория: Технические вопросы

Компании: ЛигаСтавок

Стек: JavaScript

> Пример ответа

Короткий ответ

Да, можно. Функция для запроса продуктов может возвращать промис - это стандартный паттерн в JavaScript. Промис представляет асинхронную операцию, которая завершится либо успешно с данными продуктов, либо с ошибкой. Такой подход позволяет использовать async/await, then/catch или Promise.all для параллельных запросов. Главное - правильно обработать ошибки сети, статусы ответа и валидацию данных.

Подробное объяснение

Функция, возвращающая промис, - это основа асинхронного программирования в JavaScript. Для запроса продуктов обычно используют fetch, который сам возвращает промис. Однако важно обернуть его в собственную функцию, чтобы:

  • инкапсулировать логику запроса (URL, заголовки, параметры);
  • добавить обработку ошибок (сетевые сбои, HTTP-статусы, парсинг JSON);
  • обеспечить типизацию или валидацию данных;
  • упростить тестирование и переиспользование.

Промис может быть создан тремя способами:

  1. Явно через new Promise - когда нужно контролировать асинхронную логику вручную (например, таймауты, retry).
  2. Через async функцию - она автоматически оборачивает возвращаемое значение в промис.
  3. Через fetch или другую библиотеку - они уже возвращают промис, но их нужно обернуть для добавления своей логики.

Для уровня senior важно показать понимание:

  • race conditions - если пользователь быстро меняет фильтры, старые ответы могут перезаписать новые;
  • отмены запросов - через AbortController;
  • кэширования - чтобы не делать повторные запросы;
  • обработки ошибок - не только catch, но и проверка response.ok, парсинг ошибок от сервера.

На практике

В реальном коде функция запроса продуктов обычно выглядит как модуль с конфигурацией. Она принимает параметры (фильтры, пагинацию, сортировку) и возвращает промис с нормализованными данными. Важно:

  • использовать async/await для читаемости;
  • обрабатывать ошибки через try/catch внутри функции, а не только на месте вызова;
  • возвращать единый формат ошибки (например, { error: true, message });
  • учитывать таймауты и возможность отмены.

Для senior-позиции стоит упомянуть, что промис - это не просто "обёртка над fetch", а инструмент для управления асинхронным потоком. Можно показать, как комбинировать несколько запросов через Promise.all или Promise.allSettled, как обрабатывать частичные ошибки.

Пример кода

JAVASCRIPT
// Базовый вариант с async/await
async function fetchProducts(filters = {}) {
const query = new URLSearchParams(filters).toString();
const response = await fetch(`/api/products?${query}`, {
headers: { 'Content-Type': 'application/json' },
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
return data.products; // предполагаем, что сервер возвращает { products: [...] }
}
// Вариант с отменой и таймаутом
function fetchProductsWithCancel(filters, signal) {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 5000);
const externalSignal = signal;
if (externalSignal) {
externalSignal.addEventListener('abort', () => controller.abort());
}
return fetch(`/api/products?${new URLSearchParams(filters)}`, {
signal: controller.signal,
})
.then(response => {
clearTimeout(timeoutId);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return response.json();
})
.then(data => data.products)
.catch(error => {
if (error.name === 'AbortError') {
throw new Error('Request was cancelled');
}
throw error;
});
}
// Использование
try {
const products = await fetchProducts({ category: 'electronics', page: 1 });
console.log(products);
} catch (error) {
console.error('Failed to load products:', error);
}

Как отвечать на собеседовании

Начните с прямого ответа "да", затем покажите минимальный пример с fetch. После этого углубитесь в детали:

  • объясните, почему async функция автоматически возвращает промис;
  • покажите, как обрабатывать ошибки (сетевые, HTTP, парсинг);
  • упомяните AbortController для отмены запросов;
  • обсудите кэширование и дебаунс для фильтров;
  • если спросят про new Promise - покажите, когда он нужен (например, для обёртки callback-функций).

Для senior важно продемонстрировать системное мышление: не просто "функция возвращает промис", а "как эта функция вписывается в архитектуру приложения". Расскажите про обработку гонок, мемоизацию, обработку ошибок на уровне UI.

Что проверяет интервьюер

Интервьюер оценивает:

  • понимание асинхронности в JavaScript (event loop, microtasks);
  • умение работать с fetch и обрабатывать ошибки;
  • знание продвинутых паттернов: AbortController, Promise.all, Promise.allSettled;
  • способность писать чистый, переиспользуемый код;
  • умение объяснять trade-off между async/await и then/catch;
  • понимание проблем реального мира: race conditions, таймауты, повторные запросы.

Для senior также важно показать, что вы думаете о тестируемости (инъекция зависимостей, моки) и о производительности (кэширование, дебаунс).

Типичные ошибки

  • Не проверять response.ok - считать любой ответ успешным, даже 404 или 500.
  • Забывать про try/catch - ошибка сети или парсинга упадёт необработанной.
  • Игнорировать отмену запросов - при быстрой смене фильтров старые ответы перезапишут новые.
  • Возвращать весь response вместо данных - усложняет использование функции.
  • Смешивать async/await и .then() без необходимости - код становится менее читаемым.
  • Не обрабатывать таймауты - запрос может висеть бесконечно.
  • Создавать new Promise без необходимости - если можно использовать async или fetch.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью