Что такое промисы в JS?

«Что такое промисы в JS?» — вопрос из категории JavaScript, который задают на 24% собеседований AQA / Automation. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Промис (Promise) в JavaScript — это объект, представляющий результат (успешный или неудачный) асинхронной операции, которая завершится в будущем. Это основа современной работы с асинхронным кодом в JS, заменяющая сложные цепочки колбэков («ад колбэков»).

Для QA-инженера, пишущего автотесты на JavaScript/Node.js (например, с WebDriverIO, Playwright, Cypress), понимание промисов критически важно, так как большинство операций с браузером (клики, получение текста, навигация) являются асинхронными и возвращают промисы.

Состояния промиса:

  1. pending (ожидание): Начальное состояние.
  2. fulfilled (выполнено): Операция завершилась успешно.
  3. rejected (отклонено): Операция завершилась с ошибкой.

Базовый синтаксис:

// Создание промиса (чаще используется готовые API, а не этот конструктор)
const myPromise = new Promise((resolve, reject) => {
  // Асинхронная операция, например, таймер или HTTP-запрос
  setTimeout(() => {
    const data = { id: 1, name: 'Test Item' };
    const success = true;

    if (success) {
      resolve(data); // Промис переходит в состояние fulfilled с данными
    } else {
      reject(new Error('Failed to fetch data')); // Промис переходит в состояние rejected с ошибкой
    }
  }, 1000);
});

// Обработка результата
myPromise
  .then((result) => {
    console.log('Успех:', result);
  })
  .catch((error) => {
    console.error('Ошибка:', error.message);
  })
  .finally(() => {
    console.log('Операция завершена (успех или ошибка)');
  });

Практический пример в автотесте (WebDriverIO/Playwright стиль):

// Типичная цепочка асинхронных действий в тесте
it('should login successfully', async () => {
  // Метод `browser.url` возвращает промис. `await` «ждёт» его выполнения.
  await browser.url('https://example.com/login');

  // Методы `$` (поиск) и `setValue` (ввод текста) также асинхронны
  const emailField = await $('input[type="email"]');
  await emailField.setValue('test@example.com');

  await $('#password').setValue('secret123');
  await $('button[type="submit"]').click();

  // Ожидание успешного редиректа и проверка
  await expect(browser).toHaveUrlContaining('/dashboard');
  await expect($('.welcome-message')).toHaveText('Welcome, Test User!');
});
// Ключевое слово `async` перед функцией и `await` перед промисом — это современный
// синтаксический сахар для работы с промисами, делающий код плоским и читаемым.

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

  • Promise.all([...]): Ждёт выполнения всех промисов в массиве. Если один упадёт — весь Promise.all завершится с этой ошибкой. Полезно для параллельного выполнения независимых действий.

    const [userData, productList] = await Promise.all([
      fetchUserInfo(),
      fetchProducts()
    ]);
  • Promise.race([...]): Возвращает результат первого завершившегося промиса (успешно или с ошибкой).

Итог: Промисы — это фундаментальный механизм для управления асинхронным потоком в JavaScript-тестах, позволяющий писать последовательный и надёжный код для взаимодействия с асинхронным окружением браузера.