Открыть сервис

Promise: понятие и применение в программировании

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

Определение и основные характеристики

Promise — это контракт, который гарантирует, что некоторое асинхронное действие завершится одним из двух возможных исходов: успешным выполнением (fulfilled) или отклонением (rejected). Объект Promise находится в одном из трёх состояний:

  • pending (ожидание) — начальное состояние, операция ещё не завершена;
  • fulfilled (выполнено) — операция завершилась успешно, доступен результат;
  • rejected (отклонено) — операция завершилась ошибкой, доступна причина отклонения.

Переход между состояниями возможен только один раз: из состояния pending в fulfilled или rejected. После перехода состояние объекта не может быть изменено, что обеспечивает надёжность работы с асинхронным кодом.

История возникновения

Концепция promise была предложена в конце 1970-х годов в языках функционального программирования. В 1976 году Дэниел Фридман и Дэвид Уайз описали идею «обещаний» в языке программирования. Позднее, в 1980-х, понятие развивалось в рамках исследования параллельных вычислений.

Современное распространение promise получили благодаря языку JavaScript. В 2007 году появилась библиотека Dojo Toolkit, затем в 2009 году — библиотека Kris Kowal под названием Q. В 2012 году promise были стандартизированы в спецификации Promises/A+ — открытом стандарте, описывающем поведение объектов promise для обеспечения совместимости между различными реализациями.

В 2015 году promise были включены в стандарт ECMAScript 6 (ES6) как встроенный объект языка JavaScript. Это сделало их частью базового синтаксиса и позволило использовать без подключения сторонних библиотек.

Основные методы и операции

Работа с promise строится на нескольких ключевых методах:

  • then(onFulfilled, onRejected) — основной метод, принимающий одну или две функции обратного вызова. Первая вызывается при успешном выполнении, вторая — при отклонении. Метод возвращает новый promise, что позволяет строить цепочки вызовов;
  • catch(onRejected) — сокращённая запись для обработки ошибок, эквивалентна вызову then с пропущенным первым аргументом;
  • finally(onFinally) — метод, выполняющий заданную функцию независимо от исхода операции, обычно используемый для очистки ресурсов.

Для работы с несколькими promise одновременно применяются статические методы:

  • Promise.all(iterable) — принимает массив promise и возвращает новый promise, который выполняется, когда все переданные promise выполнены, или отклоняется при первой ошибке;
  • Promise.allSettled(iterable) — ожидает завершения всех promise и возвращает массив с результатами каждого, независимо от того, были они выполнены или отклонены;
  • Promise.race(iterable) — возвращает результат первого завершившегося promise (успешного или отклонённого);
  • Promise.any(iterable) — возвращает первый успешно выполненный promise, отклоняется только если все переданные promise отклонены.

Цепочки вызовов и обработка ошибок

Одним из главных преимуществ promise является возможность построения цепочек асинхронных операций. Каждый вызов метода then возвращает новый promise, который может быть использован для следующего шага. Это позволяет избежать так называемого «ада обратных вызовов» — глубокой вложенности функций, характерной для callback-подхода.

Обработка ошибок в цепочках promise происходит централизованно: если на любом этапе возникает исключение или promise отклоняется, управление передаётся ближайшему обработчику catch в цепочке. Такая модель упрощает отладку и делает код более предсказуемым.

Создание promise

Для создания нового promise используется конструктор, принимающий функцию-исполнитель (executor) с двумя параметрами: resolve и reject. Функция-исполнитель запускается немедленно при создании объекта и должна вызвать одну из этих функций для завершения операции.

Пример создания promise на JavaScript:

``javascript const promise = new Promise((resolve, reject) => { // асинхронная операция setTimeout(() => { const success = true; if (success) { resolve('Данные получены'); } else { reject(new Error('Ошибка получения данных')); } }, 1000); }); ``

Также существует синтаксический сахар async/await, введённый в ECMAScript 2017. Функции, объявленные с ключевым словом async, автоматически возвращают promise, а оператор await позволяет приостановить выполнение функции до завершения promise, делая асинхронный код похожим на синхронный.

Применение в различных языках программирования

Хотя promise наиболее известны в экосистеме JavaScript, аналогичные концепции существуют и в других языках:

  • Python — с версии 3.5 поддерживает корутины и ключевые слова async/await; библиотека asyncio предоставляет класс Future, аналогичный promise;
  • Java — класс CompletableFuture, добавленный в Java 8, реализует схожую функциональность;
  • C# — класс Task в библиотеке .NET, используемый для асинхронного программирования;
  • Swift — с версии 5.5 введены асинхронные функции и оператор await;
  • C++ — класс std::future в стандартной библиотеке для работы с асинхронными вычислениями.

Преимущества и ограничения

К преимуществам promise относят:

  • читаемость кода и отсутствие глубокой вложенности;
  • централизованную обработку ошибок;
  • неизменяемость состояния после завершения операции;
  • возможность комбинирования нескольких асинхронных операций;
  • поддержку цепочек вызовов и параллельного выполнения.

К ограничениям можно отнести:

  • невозможность отмены операции после создания promise (в стандартной реализации JavaScript);
  • необходимость привыкания к асинхронной модели мышления;
  • потенциальное усложнение отладки при большом количестве цепочек;
  • однократность перехода между состояниями, что требует создания новых promise для повторных операций.

Связанные понятия

Promise тесно связаны с рядом других концепций асинхронного программирования:

  • Callbackфункция обратного вызова, передаваемая в асинхронную операцию; promise являются более современной альтернативой callback;
  • Event loop — механизм обработки событий в JavaScript, обеспечивающий выполнение асинхронных операций в однопоточном окружении;
  • Microtask — тип очереди задач в JavaScript, в которую помещаются обработчики promise, выполняемые до следующей макрозадачи;
  • Reactive Streamsспецификация асинхронной обработки потоков данных, используемая в Java и других языках.

BFOmetr — база данных и аналитика по компаниям России.

На главную BFOmetr →