Оглавление
- Введение в Обещания на JavaScript
- Смысловое значение Обещаний в JavaScript
- В чём отличие фактора времени от всех остальных факторов в Обещаниях (Промисах) в JavaScript?
- Зачем нужны Обещания (Промисы) в JavaScript?
- Обещание (Промис) с синтаксической стороны в JavaScript
Введение в Обещания (Промисы) на JavaScript
Что нужно знать про «Обещания (Промисы)» в языке программирования JavaScript? Самое главное то, что «Обещания (Промисы)» являются встроенным классом в сам язык. Это значит, что на любом устройстве, где есть среда выполнения кода для JavaScript будет присутствовать класс Promise. Его не нужно импортировать из какой-то библиотеки или модуля. К этому классу можно сразу обращаться по имени из любого места программы.
Все объекты языка JavaScript имеют одного единственного предка, от которого они происходят — это глобальный объект. На клиентских устройствах он имеет имя window, а на серверной стороне он именуется global.
Класс Promise является свойством глобального объекта и именно поэтому к нему можно обращаться из любого места программы напрямую по имени.
Когда мы работаем в браузере, то до класса Promise можно дотянуться двумя способами:
window.Promise или просто Promise
Консоль браузера информативная и позволяет нам немного раскрыть информацию и детально разглядеть свойство глобального объекта.
Каждый нормальный класс языка JavaScript должен иметь внутри себя функцию constructor
, которая знает по каким правилам нужно создавать новые объекты — новые экземпляры класса.
Бледным цветом обозначены свойства объектов, которые недоступны для перечисления. То есть у этих свойств атрибут [[Enumerable]] имеет значение false
. Значит эти свойства не будут участвовать в цикле for in
. То есть свойство Promise не будет отображаться при перечислении циклом for in
по глобальному объекту.
Также стоит обратить внимание на атрибут [[Configurable]]. Его значение true
говорит нам о том, что свойство Promise для глобального объекта может быть удалено или перезаписано кем угодно в среде выполнения кода.
Object.getOwnPropertyDescriptor(window, 'Promise')
Вывод информации о свойстве Promise в консоль браузера:
Смысловое значение Обещаний (Промисов) в JavaScript
Для понимания сути «Обещаний (Промисов)» нужно обратиться к ситуациям из реального мира людей.
Вы когда-нибудь давали кому-то своё обещание? Давайте посмотрим на три примера фраз с обещаниями:
- «Я обещаю купить жене машину»
- «Я обещаю закончить школу на самые высокие баллы»
- «Я натренирую свою физическую силу и смогу поднимать 200 кг от груди в жиме лёжа»
Что объединяет все эти человеческие обещания? Ключевой фактор — это время. Любое обещание упирается в понятие «времени» и его продолжительности. Можно сказать, что у обещания есть период ожидания, в течении которого что-то ещё должно происходить.
- Когда жена получит свой автомобиль? К лету? К зиме? Когда родится второй ребёнок? Когда появятся деньги у мужа?
- Когда школьник получит высокие баллы? В какой именно день и час это произойдёт? Когда он получит свою последнюю высокую оценку?
- Когда спортсмен сможет поднять 200 кг? Это будет днём или вечером? Это будет в выходной день или на буднях?
Представьте, что вы разбогатели и готовы купить жене машину. Вы приезжаете в салон, а вам говорят, что эта модель больше не выпускается производителем. Или вам продавец говорит, что такого цвета нет в продаже и ещё долго не будет. Или жена рожает тройняшек и у вас уже тупо не будет денег на покупку автомобиля.
К чему я это всё? К тому, что кроме времени есть куча факторов из-за которых можно сказать, что обещание выполнено или не выполнено. Нам только нужно учесть все эти факторы и ответить самому себе на вопрос: «Выполнено или Отклонено?».
В чём отличие фактора времени от всех остальных факторов в Обещаниях (Промисах) в JavaScript?
На время выполнения обещания мы не можем повлиять на 100%. Мы можем запланировать быть сильными через 5 месяцев, но коварная бактериальная инфекция разрушит планы и отправит спортсмена на больничную койку до 30 дней постельного режима. И это не учитывая, что спортсмен следил за питанием и тренировками, соблюдал режим и хорошо высыпался.
Зачем нужны Обещания (Промисы) в JavaScript?
Если вы прочитали всё вышеперечисленное, то вы уже догадываетесь, что Обещания (Промисы) нужны в задачах, когда фактор времени не определён. Что это за задачи такие?
Это все задачи, связанные с отправкой запросов и получение ответов на сторонние серверы или в сеть. Когда вы с браузера отправляете запрос на сайт, то вы фактически не можете сразу ответить каким маршрутом он будет доставлен до сервера данных.
Сначала запрос уходит в систему доменных имён, потом она отвечает. Затем прозванивается цепочка маршрутизаторов, по которым запрос будет переходить. Сегодня работают одни устройства, а завтра уже другие. Сеть живая и очень быстро перестраивается. Это значит, что время движения вашего запроса на получение контента будет неопределённым. А если сервер данных будет выключен, то вы вообще ничего не получите.
В итоге, если ваш сайт подгружает со стороннего источника информационный блок с погодой, то его нужно будет подождать. А когда код этого блока приедет на клиент, тогда его можно будет отрисовать. Иными словами, можно создать объект обещания, который будет ждать код блока, а потом либо отрисует его, либо нет.
Обещание (Promise) — это объект, который используется в качестве заполнителя для возможных результатов отложенного (и, возможно, асинхронного) вычисления.
Обещание (Promise) принадлежит к разделу «Управляемые Объекты Абстракции» (Control Abstraction Objects)
Обещание (Промис) с синтаксической стороны в JavaScript
Что из себя представляет класс обещаний — Promise?
Важно здесь то, что объекты Обещаний нельзя создать литерально. Создать обещание можно только при помощи функции конструктора класса.
Давайте попытаемся создать новое Обещание просто вызвав функцию конструктор без параметров.
let pr = new Promise();
Данное выражение приведёт к появлению ошибки «TypeError: Promise resolver undefined is not a function«.
Конструктору чего-то не хватает? Чего именно? Что он хочет получить?
Что принимает функция конструктор при создании Обещания?
Помните, ранее мы говорили о всевозможных условиях из-за которых можно сказать, что Обещание выполнено или нет. Так вот конструктор нового Обещания ждёт, чтобы мы передали в него логику обработки нашего Обещания. Конструктор не знает, что мы хотим проверять или сопоставлять. Конструктор не знает сколько тренировок в спортзале вам осталось, не знает сколько денег на вашем расчётном счету, не знает заболеете ли вы или нет. В общем ему нужна инструкция с действиями при различных ситуационных ветвлениях — нужна функция.
Браузер называет эту функцию условно «resolver«. На русский язык это можно перевести как «решатель«. То есть функция, которая «решает» считать ли Обещание выполненным или считать его отклонённым.
Стандарт ECMAScript условно называет данную функцию «executor«. На русский язык это можно перевести как «исполнитель«. Это звучит корректнее.
И вот тут мы подходим к ещё одному важному моменту в Обещаниях! Эта переданная функция «исполнитель» должна принимать первыми двумя параметрами две функции. Первая разрешает Обещание. Вторая отклоняет Обещание.
Давайте теперь попробуем создать новый объект Обещания, только с «исполнителем«. Пусть это будет пустая стрелочная функция, которая ничего не делает.
let pr = new Promise(()=>{});
Результат вызова:
В этот раз мы успешно создали самое примитивное Обещание в JavaScript. Наша переданная функция исполнителя в конструктор класса ничего не делает и ничего не принимает сама.
В результате наше Обещание как-бы «подвисает» в неопределённом состоянии. Мы это можем понять по значению «pending« во внутреннем слоте Обещания, который называется [[PromiseState]]. Наше Обещание ожидает выполнения, но оно никогда не будет выполнено или отклонено. Конкретно в этом примере у нас нет никаких инструкций, условий или ветвлений. Мы не передали исполнителю функцию разрешения и функцию отклонения Обещания. Тело функции исполнителя также пустое, как и блок параметров. Его нужно наполнить полезными действиями.
Но сначала нужно знать о возможных состояниях объектов Обещаний.
Состояния объектов Обещаний (Promise) в JavaScript
Любой объект Обещания (Promise) находится в одном из трёх взаимоисключающих состояний:
- fulfilled — (выполнено)
- rejected — (отклонено)
- pending — (ожидает выполнения)
Состояние fulfilled
Обещание «p» выполняется, если «p.then (f, r)» немедленно ставит Задание в очередь для вызова функции f.
Состояние rejected
Обещание «p» отклоняется, если «p.then (f, r)» немедленно ставит Задание в очередь для вызова функции r.
Состояние pending
Обещание «ожидает выполнения«, если оно не «выполнено» или не «отклонено«.
Обещание считается установившимся (settled), если оно не «ожидает выполнения«, то есть если оно «выполнено» или «отклонено«.
Обещание считается разрешённым (resolved), если оно разрешено или если оно было «зафиксировано», чтобы соответствовать состоянию другого обещания. Попытка разрешить или отклонить выполненное обещание не имеет никакого эффекта. Обещание считается неразрешённым (unresolved), если оно не разрешено. Неразрешённое обещание всегда находится в состоянии ожидания. Разрешённое обещание может быть отложено, выполнено или отклонено.
Выполненное Обещание в JavaScript
Теперь, когда мы знакомы с состояниями объектов Обещаний, мы можем принудительно создать такое Общение, которое при любых условиях всегда будет выполняться. Мы объявляем функцию исполнителя в виде стрелочной. Передаём её в конструктор Обещаний. В то же самое время, наша функция исполнитель будет принимать две функции реагирования, которые повлияют на состояние.
let p1 = new Promise((resolve, reject)=>resolve())
Мы вызвали функцию resolve() в исполнителе, поэтому наше Обещание сразу же выполнилось без каких-либо ожиданий. Мы видим слот [[PromiseState]] со значением «fulfilled«.
Отклонённое Обещание в JavaScript
Теперь мы можем создать Обещание, которое всегда будет отклонено.
let p2 = new Promise((resolve, reject)=>reject())
Слот [[PromiseState]] теперь имеет значение «rejected«. В случае отклонения Обещания будет выброшено исключение.
Условие Отклонения или Разрешения Обещания в функции исполнителе в JavaScript
Мы рассмотрели два простых случая, когда обещания 100% будут либо разрешаться, либо отклоняться. И теперь мы легко можем добавить в наш исполнитель условие разрешения или отклонения. Но чтобы было веселее, представим, что мы даём нашему тренеру Обещание выиграть соревнование через 3 месяца.
let p3 = new Promise((resolve, reject, kg = 100)=>{ if(kg > 120){ return reject('Связки порвались. Спортсмен теперь инвалид.') } else{ return resolve('Соревнование будет выиграно') } }) let p4 = new Promise((resolve, reject, kg = 150)=>{ if(kg > 120){ return reject('Связки порвались. Спортсмен теперь инвалид.') } else{ return resolve('Соревнование будет выиграно') } })
В этом примере функция исполнителя принимает дополнительный параметр «kg» — это вес штанги, которую поднимает спортсмен. Идея такая. Если штанга тяжелее 120 килограмм, тогда у спортсмена рвутся связки и он уезжает в больничку надолго. В результате это условие, при котором Обещание этого спортсмена перед тренером не будет выполнено. Но если наш спортсмен поднимает до 120 кг, тогда всё хорошо — он цел и невредим.
Абстрактные Операции Обещания по стандарту ECMAScript
- PromiseCapability Records — Записи о возможностях обещаний
- PromiseReaction Records — Записи о реакции на обещание
- CreateResolvingFunctions ( promise ) — Создание разрешающей функции
- FulfillPromise ( promise, value ) — Выполнение обещания
- NewPromiseCapability ( C ) — Новая возможность обещания
- IsPromise ( x ) — Проверка на обещание — Это обещание или нет?
- RejectPromise ( promise, reason ) — Отклонение обещания
- TriggerPromiseReactions ( reactions, argument ) — Триггерные реакции на обещание
- HostPromiseRejectionTracker ( promise, operation ) — Отслеживание отклонения обещаний хоста
PromiseCapability Records — (Записи о возможностях обещаний)
«PromiseCapability Record» — это значение записи Record, используемое для инкапсуляции объекта обещания вместе с функциями, которые способны разрешать или отклонять этот объект обещания. «PromiseCapability Record» создаются абстрактной операцией NewPromiseCapability.
В записях «PromiseCapability Record» есть поля, перечисленные в таблице 77.
Имя поля (Field Name) | Значение (Value) | Смысл (Meaning) |
[[Promise]] | Объект | Объект, который можно использовать как обещание. |
[[Resolve]] | Функциональный объект | Функция, которая используется для разрешения данного объекта обещания. |
[[Reject]] | Функциональный объект | Функция, которая используется для отклонения данного объекта обещания. |
Таблица 77: Поля записей «PromiseCapability Record»
IfAbruptRejectPromise ( value, capability )
IfAbruptRejectPromise — это сокращение для последовательности шагов алгоритма, использующих запись «PromiseCapability Record«. Шаг алгоритма вида:
1. IfAbruptRejectPromise(value, capability).
означает то же, что и:
1. Если значение value - это внезапное завершение, то 1. Выполнить ? вызов Call(capability.[[Reject]], undefined, « value.[[Value]] »). 2. Вернуть capability.[[Promise]]. 2. В противном случае, если значение value является завершенной записью (Completion Record), установите value в value.[[Value]].
PromiseReaction Records — (Записи о реакции на обещание)
«PromiseReaction» — это значение записи Record, используемое для хранения информации о том, как обещание должно реагировать, когда оно разрешается или отклоняется с заданным значением. Записи «PromiseReaction» создаются абстрактной операцией «PerformPromiseThen» и используются абстрактным замыканием (Abstract Closure), возвращаемым NewPromiseReactionJob.
Записи «PromiseReaction» содержат поля, перечисленные в таблице 78.
Имя поля (Field Name) | Значение (Value) | Смысл (Meaning) |
[[Capability]] | Запись PromiseCapability Record или undefined | Возможности обещания, для которого эта запись предоставляет обработчик реакции. |
[[Type]] | Fulfill или Reject | [[Type]] тип используется, когда обработчик [[Handler]] пуст, чтобы разрешить поведение, специфичное для типа поселения. |
[[Handler]] | Запись JobCallback Record или «empty«. | Функция, которая должна быть применена к входящему значению и возвращаемое значение которой будет определять, что происходит с производным обещанием. Если обработчик [[Handler]] является «empty» (пустым), вместо него будет использоваться функция, которая зависит от значения типа [[Type]]. |
Таблица 78: Поля записи «PromiseReaction»
CreateResolvingFunctions ( promise ) — (Создание разрешающей функции)
Абстрактная операция «CreateResolvingFunctions» принимает аргумент promise. При вызове она выполняет следующие шаги:
1. Пусть alreadyResolved будет записью Record { [[Value]]: false }. 2. Пусть stepsResolve будет шагами алгоритма, определенными в функциях разрешения обещаний (Promise Resolve Functions). 3. Пусть resolve будет ! CreateBuiltinFunction(stepsResolve, « [[Promise]], [[AlreadyResolved]] »). 4. Установить resolve.[[Promise]] на promise. 5. Установить resolve.[[AlreadyResolved]] на alreadyResolved. 6. Пусть stepsReject будут шагами алгоритма, определенными в функциях отклонения обещаний (Promise Reject Functions). 7. Пусть reject будет ! CreateBuiltinFunction(stepsReject, « [[Promise]], [[AlreadyResolved]] »). 8. Установить reject.[[Promise]] to promise. 9. Установить reject.[[AlreadyResolved]] на alreadyResolved. 10. Вернуть запись Record { [[Resolve]]: resolve, [[Reject]]: reject }.
Promise Reject Functions — (Функции отклонения обещаний)
Функция отклонения обещания — это анонимная встроенная функция, которая имеет внутренние слоты [[Promise]] и [[AlreadyResolved]].
Когда функция отклонения обещания вызывается с аргументом причины reason, выполняются следующие шаги:
1. Пусть F будет активным функциональным объектом. 2. Утверждение: F имеет внутренний слот [[Promise]], значением которого является объект Object. 3. Пусть promise будет F.[[Promise]]. 4. Пусть alreadyResolved будет F.[[AlreadyResolved]]. 5. Если alreadyResolved.[[Value]] является истиной true, тогда вернуть undefined. 6. Установить alreadyResolved.[[Value]] на true. 7. Вернуть RejectPromise(promise, reason).
Свойство «length» функции отклонения обещания равно 1.
Promise Resolve Functions — (Функции выполнения обещаний)
Функция разрешения обещаний — это анонимная встроенная функция, которая имеет внутренние слоты [[Promise]] и [[AlreadyResolved]].
Когда функция разрешения обещания вызывается с аргументом разрешения resolution, выполняются следующие шаги:
1. Пусть F будет активным функциональным объектом. 2. Утверждение: F имеет внутренний слот [[Promise]], значением которого является объект Object. 3. Пусть promise будет F.[[Promise]]. 4. Пусть alreadyResolved будет F.[[AlreadyResolved]]. 5. Если alreadyResolved.[[Value]] является истиной true, тогда вернуть undefined. 6. Установить alreadyResolved.[[Value]] на true. 7. Если SameValue(resolution, promise) является истинным true, то 1. Пусть selfResolutionError будет вновь созданным объектом TypeError. 2. Вернуть RejectPromise(promise, selfResolutionError). 8. Если тип Type(resolution) не является объектом Object, тогда 1. Вернуть FulfillPromise(promise, resolution). 9. Пусть then будет Get(resolution, "then"). 10. If then является резким завершением, то 1. Вернуть RejectPromise(promise, then.[[Value]]). 11. Пусть thenAction будет then.[[Value]]. 12. Если IsCallable(thenAction) является ложным false, то 1. Вернуть FulfillPromise(promise, resolution). 13. Пусть thenJobCallback будет HostMakeJobCallback(thenAction). 14. Пусть job будет NewPromiseResolveThenableJob(promise, resolution, thenJobCallback). 15. Выполните HostEnqueuePromiseJob(job.[[Job]], job.[[Realm]]). 16. Вернуть undefined.
Свойство «length» функции разрешения обещания равно 1.
FulfillPromise ( promise, value ) — (Выполнение обещания)
Абстрактная операция «FulfillPromise» принимает аргументы обещание promise и значение value. При вызове она выполняет следующие шаги:
1. Утверждение: значение состояния обещания promise.[[PromiseState]] является pending (ожидает выполнения). 2. Пусть reactions будет promise.[[PromiseFulfillReactions]]. 3. Установить promise.[[PromiseResult]] на value. 4. Установить promise.[[PromiseFulfillReactions]] на undefined. 5. Установить promise.[[PromiseRejectReactions]] на undefined. 6. Установить promise.[[PromiseState]] на fulfilled. 7. Вернуть TriggerPromiseReactions(reactions, value).
NewPromiseCapability ( C ) — (Новая возможность обещания)
Абстрактная операция «NewPromiseCapability» принимает аргумент C. Он пытается использовать C в качестве конструктора, как встроенный конструктор Promise, для создания объекта Promise и извлечения его функций разрешения resolve и отклонения reject. Объект Promise, а также функции разрешения resolve и отклонения reject используются для инициализации новой записи PromiseCapability. При вызове она выполняет следующие шаги:
1. Если IsConstructor(C) является ложным false, выбросить исключение TypeError. 2. ПРИМЕЧАНИЕ. Предполагается, что C является функцией-конструктором, которая поддерживает соглашения о параметрах конструктора Promise (см. 26.6.3.1). 3. Пусть promiseCapability будет the PromiseCapability Record { [[Promise]]: undefined, [[Resolve]]: undefined, [[Reject]]: undefined }. 4. Пусть шаги steps будут шагами алгоритма, определенными в функциях GetCapabilitiesExecutor. 5. Пусть исполнитель executor будет ! CreateBuiltinFunction(steps, « [[Capability]] »). 6. Установите executor.[[Capability]] на promiseCapability. 7. Пусть promise будет ? Construct(C, « executor »). 8. Если IsCallable(promiseCapability.[[Resolve]]) является ложным false, выбросить исключение TypeError. 9. Если IsCallable(promiseCapability.[[Reject]]) является ложным false, выбросить исключение TypeError. 10. Установить promiseCapability.[[Promise]] на promise. 11. Вернуть promiseCapability.
Примечание. Эта абстрактная операция поддерживает создание подклассов Promise, поскольку она универсальна для любого конструктора, который вызывает переданный аргумент функции-исполнителя так же, как конструктор Promise. Она используется для обобщения статических методов конструктора Promise на любой подкласс.
GetCapabilitiesExecutor Functions — (Функции получения возможностей исполнителя)
Функция «GetCapabilitiesExecutor» — это встроенная анонимная функция, имеющая внутренний слот [[Capability]].
Когда функция «GetCapabilitiesExecutor» вызывается с аргументами resolve и reject, выполняются следующие шаги:
1. Пусть F будет активным функциональным объектом. 2. Утверждение: F имеет внутренний слот [[Capability]], значением которого является запись PromiseCapability. 3. Пусть promiseCapability будет F.[[Capability]]. 4. Если promiseCapability.[[Resolve]] не является undefined, выбросить исключение TypeError. 5. Если promiseCapability.[[Reject]] не является undefined, выбросить исключение TypeError. 6. Установить promiseCapability.[[Resolve]] на resolve. 7. Установить promiseCapability.[[Reject]] на reject. 8. Вернуть undefined.
Свойство «length» функции GetCapabilitiesExecutor равно 2.
IsPromise ( x ) — (Проверка на обещание — Это обещание или нет?)
Абстрактная операция «IsPromise» принимает аргумент x. Она проверяет марку обещания на объект. При вызове она выполняет следующие шаги:
1. Если тип Type(x) не является объектом Object, вернуть false. 2. Если x не имеет внутреннего слота [[PromiseState]], вернуть false. 3. Вернуть true.
RejectPromise ( promise, reason ) — (Отклонение обещания)
Абстрактная операция «RejectPromise» принимает аргументы: обещание promise и причину reason. При вызове он выполняет следующие шаги:
1. Утверждение: значение promise.[[PromiseState]] является pending (ожидает выполнения). 2. Пусть reactions будет promise.[[PromiseRejectReactions]]. 3. Установить promise.[[PromiseResult]] на reason. 4. Установить promise.[[PromiseFulfillReactions]] на undefined. 5. Установить promise.[[PromiseRejectReactions]] на undefined. 6. Установить promise.[[PromiseState]] на rejected. 7. Если promise.[[PromiseIsHandled]] является ложным false, выполните HostPromiseRejectionTracker(promise, "reject"). 8. Вернуть TriggerPromiseReactions(reactions, reason).
TriggerPromiseReactions ( reactions, argument ) — (Триггерные реакции на обещание)
Абстрактная операция «TriggerPromiseReactions» принимает аргументы: реакции reactions (набор записей PromiseReaction) и аргумент argument. Она ставит новую задачу для каждой записи в реакции reactions. Каждое такое задание обрабатывает тип [[Type]] и обработчик [[Handler]] записи PromiseReaction, и, если обработчик [[Handler]] не пустой (not «empty»), вызывает его, передавая данный аргумент. Если обработчик [[Handler]] пустой («empty»), поведение определяется [[Type]]. При вызове он выполняет следующие шаги:
1. Для каждого элемента reaction из reactions (реакции из реакций) в исходном порядке вставки выполните 1. Пусть job будет NewPromiseReactionJob(reaction, argument). 2. Выполнить HostEnqueuePromiseJob(job.[[Job]], job.[[Realm]]). 2. Вернуть undefined.
HostPromiseRejectionTracker ( promise, operation ) — (Отслеживание отклонения обещаний хоста)
HostPromiseRejectionTracker — это абстрактная операция, определяемая хостом, которая позволяет средам узла отслеживать отклонения обещаний.
Реализация HostPromiseRejectionTracker должна завершаться нормально во всех случаях. Реализация HostPromiseRejectionTracker по умолчанию должна безоговорочно возвращать пустое нормальное завершение.
Примечание 1.
HostPromiseRejectionTracker вызывается в двух сценариях:
- Когда обещание отклоняется без каких-либо обработчиков, оно вызывается с аргументом операции operation, установленным на «reject«.
- Когда обработчик добавляется к отклоненному обещанию в первый раз, он вызывается с аргументом операции operation, установленным на «handle«.
Типичная реализация HostPromiseRejectionTracker может пытаться уведомить разработчиков о необработанных отказах, а также быть осторожным, чтобы уведомить их, если такие предыдущие уведомления позже станут недействительными из-за присоединения новых обработчиков.
Примечание 2
Если операция operation является «handle«, реализация не должна содержать ссылку на обещание promise таким образом, чтобы это мешало сборке мусора. Реализация может содержать ссылку на обещание promise, если операция operation является «reject» (отклонённой), поскольку ожидается, что отклонения будут редкими, а не на горячих путях кода.
Задания Обещания
- NewPromiseReactionJob ( reaction, argument )
- NewPromiseResolveThenableJob ( promiseToResolve, thenable, then )
NewPromiseReactionJob ( reaction, argument )
Абстрактная операция «NewPromiseReactionJob» принимает аргументы, реакцию reaction и аргумент argument. Она возвращает новое задание Job абстрактное замыкание (Abstract Closure), которое применяет соответствующий обработчик к входящему значению и использует возвращаемое значение обработчика для разрешения или отклонения производного обещания, связанного с этим обработчиком. При вызове она выполняет следующие шаги:
1. Пусть job будет новым Job абстрактным замыканием (Abstract Closure) без параметров, которое фиксирует reaction и argument и при вызове выполняет следующие шаги: a. Утверждение: реакция reaction - это запись PromiseReaction Record. b. Пусть promiseCapability будет reaction.[[Capability]]. c. Пусть type будет reaction.[[Type]]. d. Пусть handler будет reaction.[[Handler]]. e. Если handler является "empty", то i. Если type is Fulfill, пусть handlerResult будет NormalCompletion(argument). ii. Иначе, 1. Утверждение: type является Reject. 2. Пусть handlerResult будет ThrowCompletion(argument). f. Иначе, пусть handlerResult будет HostCallJobCallback(handler, undefined, « argument »). g. Если promiseCapability является undefined, то i. Утверждение: handlerResult не является внезапным завершением. ii. Вернуть NormalCompletion("empty"). h. Утверждение: promiseCapability является PromiseCapability Record. i. Если handlerResult является внезапным завершением, то i. Пусть status будет вызовом Call(promiseCapability.[[Reject]], undefined, « handlerResult.[[Value]] »). j. Иначе, i. Пусть status будет вызовом Call(promiseCapability.[[Resolve]], undefined, « handlerResult.[[Value]] »). k. Вернуть Completion(status). 2. Пусть handlerRealm будет null. 3. Если reaction.[[Handler]] не является "empty", то a. Пусть getHandlerRealmResult будет GetFunctionRealm(reaction.[[Handler]].[[Callback]]). b. Если getHandlerRealmResult является нормальным завершением, установите для handlerRealm значение getHandlerRealmResult.[[Value]]. c. В противном случае установите handlerRealm на текущую запись Realm Record. d. ПРИМЕЧАНИЕ: handlerRealm никогда не имеет значения null, если только обработчик является undefined. Когда обработчик является отозванным прокси и не запускается код ECMAScript, для создания объектов ошибок используется handlerRealm. 4. Вернуть запись Record { [[Job]]: job, [[Realm]]: handlerRealm }.
NewPromiseResolveThenableJob ( promiseToResolve, thenable, then )
Абстрактная операция «NewPromiseResolveThenableJob» принимает аргументы promiseToResolve, thenable и then. При вызове она выполняет следующие шаги:
1. Пусть job будет новым абстрактным замыканием Job Abstract Closure без параметров, которое захватывает promiseToResolve, thenable и then и при вызове выполняет следующие шаги: a. Пусть resolvingFunctions будет CreateResolvingFunctions(promiseToResolve). b. Пусть thenCallResult будет HostCallJobCallback(then, thenable, « resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]] »). c. Если thenCallResult является внезапным завершением, то i. Пусть status будет вызовом Call(resolvingFunctions.[[Reject]], undefined, « thenCallResult.[[Value]] »). ii. Вернуть Completion(status). d. Вернуть Completion(thenCallResult). 2. Пусть getThenRealmResult будет GetFunctionRealm(then.[[Callback]]). 3. Если getThenRealmResult является нормальным завершением, пусть thenRealm будет getThenRealmResult.[[Value]]. 4. В противном случае пусть thenRealm будет текущей записью Realm Record. 5. ПРИМЕЧАНИЕ: thenRealm никогда не имеет значения null. Когда then.[[Callback]] - это отозванный прокси и никакой код не запускается, thenRealm используется для создания объектов ошибок. 6. Вернуть запись Record { [[Job]]: job, [[Realm]]: thenRealm }.
Примечание
Это задание Job использует предоставленный thenable и его метод then для разрешения данного обещания. Этот процесс должен выполняться как задание, чтобы гарантировать, что оценка метода then происходит после завершения оценки любого окружающего кода.
Конструктор Обещания
Конструктор Promise:
- это %Promise%.
- это начальное значение свойства «Promise» глобального объекта.
- создает и инициализирует новый объект Promise при вызове в качестве конструктора.
- не предназначен для вызова в качестве функции и при таком вызове вызовет исключение.
- предназначен для создания подклассов. Он может использоваться как значение в предложении «extends» определения класса. Конструкторы подкласса, которые намереваются наследовать указанное поведение Promise, должны включать супер-вызов «super» конструктора Promise для создания и инициализации экземпляра подкласса с внутренним состоянием, необходимым для поддержки встроенных методов Promise и Promise.prototype.
Promise ( executor )
Когда функция Promise вызывается с исполнителем аргументов — (executor), выполняются следующие шаги:
1. Если NewTarget является "undefined", выбросить исключение TypeError. 2. Если IsCallable(executor) имеет значение false, выбросить исключение TypeError. 3. Пусть promise будет ? OrdinaryCreateFromConstructor(NewTarget, "%Promise.prototype%", « [[PromiseState]], [[PromiseResult]], [[PromiseFulfillReactions]], [[PromiseRejectReactions]], [[PromiseIsHandled]] »). 4. Установить promise.[[PromiseState]] на "pending". 5. Установить promise.[[PromiseFulfillReactions]] в новый пустой Список. 6. Установить promise.[[PromiseRejectReactions]] в новый пустой Список. 7. Установить promise.[[PromiseIsHandled]] значение false. 8. Пусть resolvingFunctions будет CreateResolvingFunctions(promise). 9. Пусть completion будет Вызовом(executor, undefined, « resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]] »). 10. Если completion является внезапным завершением, тогда 1. Выполнить ? Вызов(resolvingFunctions.[[Reject]], undefined, « completion.[[Value]] »). 11. Вернуть promise
Примечание
Аргумент исполнителя (executor) должен быть функциональным объектом (function object). Он вызывается для инициирования и сообщения о завершении возможного отложенного действия, представленного этим объектом Promise. Исполнитель вызывается с двумя аргументами: разрешить (resolve) и отклонить (reject). Это функции, которые могут использоваться функцией-исполнителем (executor) для сообщения о конечном завершении или сбое отложенного вычисления. Возврат от функции-исполнителя не означает, что отложенное действие было завершено, а только то, что запрос на выполнение отложенного действия был принят.
Функция разрешения (resolve), переданная в функцию-исполнитель (executor), принимает единственный аргумент. Код исполнителя (executor) может в конечном итоге вызвать функцию разрешения (resolve), чтобы указать, что он хочет разрешить связанный объект Promise. Аргумент, переданный функции разрешения (resolve), представляет конечное значение отложенного действия и может быть либо фактическим значением выполнения, либо другим объектом Promise, который предоставит значение, если оно будет выполнено.
Функция отклонения (reject), переданная в функцию-исполнитель (executor), принимает единственный аргумент. Код исполнителя (executor) может в конечном итоге вызвать функцию отклонения (reject), чтобы указать, что связанное обещание Promise отклонено и никогда не будет выполнено. Аргумент, переданный функции отклонения (reject), используется как значение отклонения обещания. Обычно это объект Error.
Функции разрешения и отклонения, переданные функции-исполнителю (executor) конструктором Promise, могут фактически разрешить и отклонить связанное обещание. Подклассы могут иметь различное поведение конструктора, которое передает настраиваемые значения для разрешения и отклонения.
Свойства конструктора Обещания
- Promise.all ( iterable )
- Promise.allSettled ( iterable )
- Promise.any ( iterable )
- Promise.prototype
- Promise.race ( iterable )
- Promise.reject ( r )
- Promise.resolve ( x )
- get Promise [ @@species ]
Конструктор Promise:
- имеет внутренний слот [[Prototype]], значение которого — %Function.prototype%.
- имеет следующие свойства:
Promise.all ( iterable )
Функция «all» возвращает новое обещание, которое выполняется с массивом значений выполнения для переданных обещаний, или отклоняет по причине первого переданного обещания, которое отклоняется. Он преобразует все элементы переданной итерации в обещания по мере выполнения этого алгоритма.
1. Пусть C будет значением this. 2. Пусть promiseCapability будет ? NewPromiseCapability(C). 3 Пусть promiseResolve будет GetPromiseResolve(C). 4. IfAbruptRejectPromise(promiseResolve, promiseCapability). 5. Пусть iteratorRecord будет GetIterator(iterable). 6. IfAbruptRejectPromise(iteratorRecord, promiseCapability). 7. Пусть результатом будет PerformPromiseAll(iteratorRecord, C, promiseCapability, promiseResolve). 8. Если результат result - внезапное завершение, тогда 1. Если iteratorRecord.[[Done]] имеет значение false, установите для результата result значение IteratorClose(iteratorRecord, result). 2. IfAbruptRejectPromise(result, promiseCapability). 9. Вернуть Completion(result).
Примечание! Функция «all» требует, чтобы значение this было функцией-конструктором, которая поддерживает соглашения о параметрах конструктора Promise.
Семантика времени выполнения: GetPromiseResolve ( promiseConstructor )
Абстрактная операция «GetPromiseResolve» принимает аргумент promiseConstructor. При вызове он выполняет следующие шаги:
1. Утверждение: IsConstructor(promiseConstructor) является true. 2. Пусть promiseResolve будет ? Get(promiseConstructor, "resolve"). 3. Если IsCallable(promiseResolve) имеет значение false, выбросить исключение TypeError. 4. Вернуть promiseResolve.
Семантика времени выполнения: PerformPromiseAll ( iteratorRecord, constructor, resultCapability, promiseResolve )
Абстрактная операция «PerformPromiseAll» принимает аргументы iteratorRecord, constructor, resultCapability (запись PromiseCapability Record) и promiseResolve. При вызове она выполняет следующие шаги:
1. Утверждение: IsConstructor(constructor) является true. 2. Утверждение: IsConstructor(promiseResolve) является true. 3. Пусть значение values будет новым пустым Списком. 4. Пусть оставшееся значение элемента remainingElementsCount будет Записью { [[Value]]: 1 }. 5. Пусть index равен 0. 6. Повторять, 1. Пусть next будет IteratorStep(iteratorRecord). 2. Если next является внезапным завершением, установите для iteratorRecord.[[Done]] значение true. 3. ReturnIfAbrupt(next). 4. Если next является false, тогда 1. Установите для iteratorRecord. [[Done]] значение true. 2. Установить для remainingElementsCount.[[Value]] значение remainingElementsCount.[[Value]] - 1. 3. Если remainingElementsCount.[[Value]] равно 0, тогда 1. Пусть valuesArray будет ! CreateArrayFromList(values). 2. Выполнить? Вызов(resultCapability.[[Resolve]], undefined, « valuesArray »). 4. Вернуть resultCapability.[[Promise]]. 5. Пусть nextValue будет IteratorValue(next). 6. Если nextValue является внезапным завершением, установите для iteratorRecord.[[Done]] значение true. 7. ReturnIfAbrupt(nextValue). 8. Добавьте undefined к values. 9. Пусть nextPromise будет ? Вызов(promiseResolve, constructor, « nextValue »). 10. Пусть steps будут шагами алгоритма, определенными в Promise.all, в функции элемента Resolve. 11. Пусть resolveElement будет ! CreateBuiltinFunction(steps, « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »). 12. Установите resolveElement.[[AlreadyCalled]] в Запись Record { [[Value]]: false }. 13. Установите resolveElement.[[Index]] в index. 14. Установите resolveElement.[[Values]] в values. 15. Установите resolveElement.[[Capability]] в resultCapability. 16. Установиет resolveElement.[[RemainingElements]] в remainingElementsCount. 17. Установите remainingElementsCount.[[Value]] в remainingElementsCount.[[Value]] + 1. 18. Выполните ? Invoke(nextPromise, "then", « resolveElement, resultCapability.[[Reject]] »). 19. Установите index в index + 1.
Promise.all Resolve Element Functions
Функция элемента разрешения Promise.all — это анонимная встроенная функция, которая используется для разрешения определенного элемента Promise.all. Каждая функция элемента разрешения Promise.all имеет внутренние слоты [[Index]], [[Values]], [[Capability]], [[RemainingElements]] и [[AlreadyCalled]].
Когда функция элемента решения Promise.all вызывается с аргументом x, выполняются следующие шаги:
1. Пусть F будет активным функциональным объектом. 2. Пусть alreadyCalled будет F.[[AlreadyCalled]]. 3. Если alreadyCalled.[[Value]] является true, вернуть undefined. 4. Установите alreadyCalled.[[Value]] в значение true. 5. Пусть index будет F.[[Index]]. 6. Пусть values будет F.[[Values]]. 7. Пусть promiseCapability будет F.[[Capability]]. 8. Пусть remainingElementsCount будет F.[[RemainingElements]]. 9. Установить для values[index] значение x. 10. Установить для remainingElementsCount.[[Value]] значение remainingElementsCount.[[Value]] - 1. 11. Если remainingElementsCount.[[Value]] равно 0, тогда 1. Пусть valuesArray будет ! CreateArrayFromList(values). 2. Вернуть ? вызов Call(promiseCapability.[[Resolve]], undefined, « valuesArray »). 12. Вернуть undefined.
Свойство «length» функции элемента разрешения Promise.all равно 1.
Promise.allSettled ( iterable )
Функция «allSettled» возвращает обещание, которое выполняется с помощью массива моментальных снимков состояния обещания, но только после того, как все исходные обещания урегулируются, т.е. становятся либо выполненными, либо отклоненными. Он преобразует все элементы переданной итерации в обещания по мере выполнения этого алгоритма.
1. Пусть C будет значением this. 2. Пусть promiseCapability будет ? NewPromiseCapability(C). 3. Пусть promiseResolve будет GetPromiseResolve(C). 4. IfAbruptRejectPromise(promiseResolve, promiseCapability). 5. Пусть iteratorRecord будет GetIterator(iterable). 6. IfAbruptRejectPromise(iteratorRecord, promiseCapability). 7. Пусть result будет PerformPromiseAllSettled(iteratorRecord, C, promiseCapability, promiseResolve). 8. Если result - внезапное завершение, то a. Если iteratorRecord.[[Done]] является ложью false, установить result на IteratorClose(iteratorRecord, result). b. IfAbruptRejectPromise(result, promiseCapability). 9. Вернуть Completion(result).
Примечание
Функция «allSettled» требует, чтобы значение this было функцией-конструктором, которая поддерживает соглашения о параметрах конструктора Promise.
Семантика времени выполнения: PerformPromiseAllSettled ( iteratorRecord, constructor, resultCapability, promiseResolve )
Абстрактная операция «PerformPromiseAllSettled» принимает аргументы iteratorRecord, constructor, resultCapability (a PromiseCapability Record) и promiseResolve. При вызове она выполняет следующие шаги:
1. Утверждение: ! IsConstructor(constructor) является истиной true. 2. Утверждение: IsCallable(promiseResolve) является истиной true. 3. Пусть values будет новым пустым списком List. 4. Пусть remainingElementsCount будет записью Record { [[Value]]: 1 }. 5. Пусть index будет 0. 6. Повторять, a. Пусть next будет шагом итератора IteratorStep(iteratorRecord). b. Если next - это внезапное завершение, установите для iteratorRecord.[[Done]] значение true. c. ReturnIfAbrupt(next). d. Если next является ложью false, то i. Установить iteratorRecord.[[Done]] на true. ii. Установить remainingElementsCount.[[Value]] на remainingElementsCount.[[Value]] - 1. iii. Если remainingElementsCount.[[Value]] является 0, то 1. Пусть valuesArray будет ! CreateArrayFromList(values). 2. Выполнить? вызов Call(resultCapability.[[Resolve]], undefined, «valuesArray»). iv. Вернуть resultCapability.[[Promise]]. e. Пусть nextValue будет значением итератора IteratorValue(next). f. Если nextValue является внезапным завершением, установите для iteratorRecord.[[Done]] значение true. g. ReturnIfAbrupt(nextValue). h. Добавить undefined к values. i. Пусть nextPromise будет ? вызовом Call(promiseResolve, constructor, « nextValue »). j. Пусть steps будут шагами алгоритма, определенными в функциях элемента разрешения Resolve - Promise.allSettled. k. Пусть resolveElement будет ! CreateBuiltinFunction(steps, « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »). l. Пусть alreadyCalled будет the записью Record { [[Value]]: false }. m. Установить resolveElement.[[AlreadyCalled]] на alreadyCalled. n. Установить resolveElement.[[Index]] на index. o. Установить resolveElement.[[Values]] на values. p. Установить resolveElement.[[Capability]] на resultCapability. q. Установить resolveElement.[[RemainingElements]] на remainingElementsCount. r. Пусть rejectSteps будет шагами алгоритма, определенными в функциях элемента отклонения Reject - Promise.allSettled. s. Пусть rejectElement будет ! CreateBuiltinFunction(rejectSteps, « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »). t. Установить rejectElement.[[AlreadyCalled]] на alreadyCalled. u. Установить rejectElement.[[Index]] на index. v. Установить rejectElement.[[Values]] на values. w. Установить rejectElement.[[Capability]] на resultCapability. x. Установить rejectElement.[[RemainingElements]] на remainingElementsCount. y. Установить remainingElementsCount.[[Value]] на remainingElementsCount.[[Value]] + 1. z. Выполнить ? Invoke(nextPromise, "then", « resolveElement, rejectElement »). aa. Установить index на index + 1.
Promise.allSettled — Resolve Element Functions (функции элемента разрешения)
Функция элемента разрешения Promise.allSettled — это анонимная встроенная функция, которая используется для разрешения определенного элемента Promise.allSettled. Каждая функция элемента разрешения Promise.allSettled имеет внутренние слоты [[Index]], [[Values]], [[Capability]], [[RemainingElements]] и [[AlreadyCalled]].
Когда функция элемента разрешения Promise.allSettled вызывается с аргументом x, выполняются следующие шаги:
1. Пусть F будет активным функциональным объектом. 2. Пусть alreadyCalled будет F.[[AlreadyCalled]]. 3. Если alreadyCalled.[[Value]] является истиной true, вернуть undefined. 4. Установить alreadyCalled.[[Value]] на истину true. 5. Пусть index будет F.[[Index]]. 6. Пусть values будет F.[[Values]]. 7. Пусть promiseCapability будет F.[[Capability]]. 8. Пусть remainingElementsCount будет F.[[RemainingElements]]. 9. Пусть obj будет ! OrdinaryObjectCreate(%Object.prototype%). 10. Выполнить! CreateDataPropertyOrThrow(obj, "status", "fulfilled"). 11. Выполнить ! CreateDataPropertyOrThrow(obj, "value", x). 12. Установить values[index] на obj. 13. Установить remainingElementsCount.[[Value]] на remainingElementsCount.[[Value]] - 1. 14. Если remainingElementsCount.[[Value]] является 0, то a. Пусть valuesArray будет ! CreateArrayFromList(values). b. Вернуть ? вызов Call(promiseCapability.[[Resolve]], undefined, « valuesArray »). 15. Вернуть undefined.
Свойство «length» функции элемента разрешения Promise.allSettled равно 1.
Promise.allSettled — Reject Element Functions (функции элемента отклонения)
Функция отклонения элемента Promise.allSettled — это анонимная встроенная функция, которая используется для отклонения определенного элемента Promise.allSettled. Каждая функция отклоняющего элемента Promise.allSettled имеет внутренние слоты [[Index]], [[Values]], [[Capability]], [[RemainingElements]] и [[AlreadyCalled]].
Когда функция отклоняемого элемента Promise.allSettled вызывается с аргументом x, выполняются следующие шаги:
1. Пусть F будет активным функциональным объектом. 2. Пусть alreadyCalled будет F.[[AlreadyCalled]]. 3. Если alreadyCalled.[[Value]] является истиной true, вернуть undefined. 4. Установить alreadyCalled.[[Value]] на истину true. 5. Пусть index будет F.[[Index]]. 6. Пусть values будет F.[[Values]]. 7. Пусть promiseCapability будет F.[[Capability]]. 8. Пусть remainingElementsCount будет F.[[RemainingElements]]. 9. Пусть obj будет ! OrdinaryObjectCreate(%Object.prototype%). 10. Выполнить ! CreateDataPropertyOrThrow(obj, "status", "rejected"). 11. Выполнить ! CreateDataPropertyOrThrow(obj, "reason", x). 12. Установить values[index] на obj. 13. Установить remainingElementsCount.[[Value]] на remainingElementsCount.[[Value]] - 1. 14. Если remainingElementsCount.[[Value]] является 0, то a. Пусть valuesArray будет ! CreateArrayFromList(values). b. Вернуть ? вызов Call(promiseCapability.[[Resolve]], undefined, « valuesArray »). 15. Вернуть undefined.
Свойство «length» функции отклоняемого элемента Promise.allSettled равно 1.
Promise.any ( iterable )
Функция «any» возвращает обещание, которое выполняется первым заданным обещанием, которое должно быть выполнено, или отклоняется с помощью AggregateError, содержащего причины отклонения, если все данные обещания отклонены. Он преобразует все элементы переданной итерации в обещания по мере выполнения этого алгоритма.
1. Пусть C будет значением this. 2. Пусть promiseCapability будет ? NewPromiseCapability(C). 3. Пусть promiseResolve будет GetPromiseResolve(C). 4. IfAbruptRejectPromise(promiseResolve, promiseCapability). 5. Пусть iteratorRecord будет GetIterator(iterable). 6. IfAbruptRejectPromise(iteratorRecord, promiseCapability). 7. Пусть result будетe PerformPromiseAny(iteratorRecord, C, promiseCapability, promiseResolve). 8. Если result - внезапное завершение, то a. Если iteratorRecord.[[Done]] является ложным false, установить result на IteratorClose(iteratorRecord, result). b. IfAbruptRejectPromise(result, promiseCapability). 9. Вернуть Completion(result).
Функция «any» требует, чтобы значение this было функцией-конструктором, которая поддерживает соглашения о параметрах конструктора Promise.
Семантика времени выполнения: PerformPromiseAny ( iteratorRecord, constructor, resultCapability, promiseResolve )
Абстрактная операция «PerformPromiseAny» принимает аргументы iteratorRecord, constructor, resultCapability (a PromiseCapability Record), and promiseResolve. При вызове она выполняет следующие шаги:
1. Утверждение: ! IsConstructor(constructor) является истиной true. 2. Утверждение: ! IsCallable(promiseResolve) является истиной true. 3. Пусть ошибки errors будут новым пустым списком List. 4. Пусть remainingElementsCount будет запись Record { [[Value]]: 1 }. 5. Пусть index будет 0. 6. Повторять, a. Пусть next будет IteratorStep(iteratorRecord). b. Если next является внезапным завершением, установить iteratorRecord.[[Done]] в значение true. c. ReturnIfAbrupt(next). d. Если next является ложью false, то i. Установить iteratorRecord.[[Done]] в значение true. ii. Установить remainingElementsCount.[[Value]] на remainingElementsCount.[[Value]] - 1. iii. Если remainingElementsCount.[[Value]] равен 0, то 1. Пусть error будет только что созданным объектом AggregateError. 2. Выполнить ! DefinePropertyOrThrow(error, "errors", PropertyDescriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: ! CreateArrayFromList(errors) }). 3. Вернуть ThrowCompletion(error). iv. Вернуть resultCapability.[[Promise]]. e. Пусть nextValue будет IteratorValue(next). f. Если nextValue является внезапным завершением, установите для iteratorRecord.[[Done]] значение true. g. ReturnIfAbrupt(nextValue). h. Добавить undefined к ошибкам error. i. Пусть nextPromise будет ? вызов Call(promiseResolve, constructor, « nextValue »). j. Пусть шаги steps будут шагами алгоритма, определенными в функциях отклонения элемента Promise.any Reject Element Functions. k. Пусть rejectElement будет ! CreateBuiltinFunction(steps, « [[AlreadyCalled]], [[Index]], [[Errors]], [[Capability]], [[RemainingElements]] »). l. Установить rejectElement.[[AlreadyCalled]] на запись Record { [[Value]]: false }. m. Установить rejectElement.[[Index]] на index. n. Установить rejectElement.[[Errors]] на errors. o. Установить rejectElement.[[Capability]] на resultCapability. p. Установить rejectElement.[[RemainingElements]] на remainingElementsCount. q. Установить remainingElementsCount.[[Value]] на remainingElementsCount.[[Value]] + 1. r. Выполнить? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], rejectElement »). s. Установить index на index + 1.
Promise.any — Reject Element Functions (функции элемента отклонения)
Функция отклонения элемента Promise.any — это анонимная встроенная функция, которая используется для отклонения определенного элемента Promise.any. Каждая функция отклоняющего элемента Promise.any имеет внутренние слоты [[Index]], [[Errors]], [[Capability]], [[RemainingElements]] и [[AlreadyCalled]].
Когда вызывается функция элемента отклонения Promise.any с аргументом x, выполняются следующие шаги:
1. Пусть F будет активным функциональным объектом. 2. Пусть alreadyCalled будет F.[[AlreadyCalled]]. 3. Если alreadyCalled.[[Value]] является истиной true, вернуть undefined. 4. Установить alreadyCalled.[[Value]] на истину true. 5. Пусть index будет F.[[Index]]. 6. Пусть errors будут F.[[Errors]]. 7. Пусть promiseCapability будет F.[[Capability]]. 8. Пусть remainingElementsCount будет F.[[RemainingElements]]. 9. Установить errors[index] на x. 10. Установить remainingElementsCount.[[Value]] на remainingElementsCount.[[Value]] - 1. 11. Если remainingElementsCount.[[Value]] является 0, то a. Пусть error будет только что созданным объектом AggregateError. b. Выполнить ! DefinePropertyOrThrow(error, "errors", PropertyDescriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: ! CreateArrayFromList(errors) }). c. Вернуть ? вызов Call(promiseCapability.[[Reject]], undefined, « error »). 12. Вернуть undefined.
Свойство «length» функции отклоняемого элемента Promise.any равно 1.
Promise.prototype
Начальным значением Promise.prototype является объект-прототип Promise.
Это свойство имеет атрибуты {[[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false}.
Promise.race ( iterable )
Функция гонки «race» возвращает новое обещание, которое рассчитывается таким же образом, как и первое переданное обещание. Он преобразует все элементы переданной итерации в обещания по мере выполнения этого алгоритма.
1. Пусть C будет значением this. 2. Пусть promiseCapability будет ? NewPromiseCapability(C). 3. Пусть promiseResolve будет GetPromiseResolve(C). 4. IfAbruptRejectPromise(promiseResolve, promiseCapability). 5. Пусть iteratorRecord будет GetIterator(iterable). 6. IfAbruptRejectPromise(iteratorRecord, promiseCapability). 7. Пусть result будет PerformPromiseRace(iteratorRecord, C, promiseCapability, promiseResolve). 8. Если результат result - внезапное завершение, то a. Если iteratorRecord.[[Done]] является ложью false, установить result на IteratorClose(iteratorRecord, result). b. IfAbruptRejectPromise(result, promiseCapability). 9. Вернуть Completion(result).
Примечание 1
Если аргумент iterable пуст или если ни одно из обещаний в iterable не выполняется, то ожидающее обещание, возвращаемое этим методом, никогда не будет выполнено.
Примечание 2
Функция «race» ожидает, что значение this будет функцией-конструктором, которая поддерживает соглашения о параметрах конструктора Promise. Она также ожидает, что значение this предоставляет метод разрешения resolve.
Семантика времени выполнения: PerformPromiseRace ( iteratorRecord, constructor, resultCapability, promiseResolve )
Абстрактная операция «PerformPromiseRace» принимает аргументы iteratorRecord, constructor, resultCapability (a PromiseCapability Record), and promiseResolve. При вызове она выполняет следующие шаги:
1. Утверждение: IsConstructor(constructor) является истиной true. 2. Утверждение: IsCallable(promiseResolve) является истиной true. 3. Повторять, a. Пусть next будет IteratorStep(iteratorRecord). b. Если next - внезапное завершение, установите для iteratorRecord.[[Done]] значение true. c. ReturnIfAbrupt(next). d. Если next является ложью false, то i. Установить iteratorRecord.[[Done]] на true. ii. Вернуть resultCapability.[[Promise]]. e. Пусть nextValue будет IteratorValue(next). f. Если nextValue является внезапным завершением, установите для iteratorRecord.[[Done]] значение true. g. ReturnIfAbrupt(nextValue). h. Пусть nextPromise будет ? вызов Call(promiseResolve, constructor, « nextValue »). i. Выполнить? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], resultCapability.[[Reject]] »).
Promise.reject ( r )
Функция reject возвращает новое обещание, отклоненное переданным аргументом.
1. Пусть C будет значением this. 2. Пусть promiseCapability будет ? NewPromiseCapability(C). 3. Выполнить ? вызов Call(promiseCapability.[[Reject]], undefined, « r »). 4. Вернуть promiseCapability.[[Promise]].
Примечание
Функция reject ожидает, что значение this будет функцией конструктора, которая поддерживает соглашения о параметрах конструктора Promise.
Promise.resolve ( x )
Функция разрешения resolve возвращает либо новое обещание, разрешенное с помощью переданного аргумента, либо сам аргумент, если аргумент является обещанием, созданным этим конструктором.
1. Пусть C будет значением this. 2. Если тип Type(C) не является объектом Object, вызовите исключение TypeError. 3. Вернуть ? PromiseResolve(C, x).
Примечание
Функция разрешения resolve ожидает, что это значение будет функцией конструктора, которая поддерживает соглашения о параметрах конструктора Promise.
PromiseResolve ( C, x )
Абстрактная операция «PromiseResolve» принимает аргументы C (конструктор) и x (значение языка ECMAScript). Она возвращает новое обещание, разрешенное с помощью x. При вызове она выполняет следующие шаги:
1. Утверждение: тип Type(C) является объектом Object. 2. Если IsPromise(x) является истиной true, то a. Пусть xConstructor будет ? Get(x, "constructor"). b. Если SameValue(xConstructor, C) является истиной true, вернуть x. 3. Пусть promiseCapability будет ? NewPromiseCapability(C). 4. Выполнить ? вызов Call(promiseCapability.[[Resolve]], undefined, «x»). 5. Вернуть promiseCapability.[[Promise]].
get Promise [ @@species ]
Promise[@@species] — это свойство доступа, функция доступа которого не определена. Его функция доступа get выполняет следующие шаги:
1. Вернуть значение this.
Значение свойства «name» этой функции — «get [Symbol.species]».
Примечание
Методы прототипа обещания обычно используют свой конструктор значения this для создания производного объекта. Однако конструктор подкласса может переопределить это поведение по умолчанию, переопределив свое свойство @@species.
Свойства объекта-прототипа Обещания
- Promise.prototype.catch ( onRejected )
- Promise.prototype.constructor
- Promise.prototype.finally ( onFinally )
- Promise.prototype.then ( onFulfilled, onRejected )
- Promise.prototype [ @@toStringTag ]
Promise.prototype.catch ( onRejected )
Когда метод catch вызывается с аргументом onRejected, выполняются следующие шаги:
1. Пусть promise будет значением this. 2. Вернуть ? Invoke(promise, "then", « undefined, onRejected »).
Promise.prototype.constructor
Начальное значение Promise.prototype.constructor — это %Promise%.
Promise.prototype.finally ( onFinally )
Когда метод finally вызывается с аргументом onFinally, выполняются следующие шаги:
1. Пусть promise будет значением this. 2. Если тип Type(promise) не является объектом Object, вызовите исключение TypeError. 3. Пусть C будет ? SpeciesConstructor(promise, %Promise%). 4. Утверждение: IsConstructor(C) является истиной true. 5. Если IsCallable(onFinally) является ложью false, то a. Пусть thenFinally будет onFinally. b. Пусть catchFinally будет onFinally. 6. Иначе, a. Пусть stepsThenFinally будет шагами алгоритма, определенными в Then Finally Functions. b. Пусть thenFinally будет ! CreateBuiltinFunction(stepsThenFinally, « [[Constructor]], [[OnFinally]] »). c. Установить thenFinally.[[Constructor]] to C. d. Установить thenFinally.[[OnFinally]] на onFinally. e. Пусть stepsCatchFinally будет шагами алгоритма, определенными в Catch Finally Functions. f. Пусть catchFinally будет! CreateBuiltinFunction(stepsCatchFinally, « [[Constructor]], [[OnFinally]] »). g. Установить catchFinally.[[Constructor]] на C. h. Установить catchFinally.[[OnFinally]] на onFinally. 7. Вернуть ? Invoke(promise, "then", « thenFinally, catchFinally »).
Then Finally Functions
Функция «Then Finally» — это анонимная встроенная функция, которая имеет внутренний слот [[Constructor]] и [[OnFinally]]. Значение внутреннего слота [[Constructor]] — это объект функции конструктора, подобный Promise, а значение внутреннего слота [[OnFinally]] — это объект функции.
Когда функция «Then Finally» вызывается с аргументом value, выполняются следующие шаги:
1. Пусть F будет активным функциональным объектом. 2. Пусть onFinally будет F.[[OnFinally]]. 3. Утверждение: IsCallable(onFinally) является истиной true. 4. Пусть result будет ? вызов Call(onFinally, undefined). 5. Пусть C будет F.[[Constructor]]. 6. Утверждение: IsConstructor(C) является истиной true. 7. Пусть promise будет ? PromiseResolve(C, result). 8. Пусть valueThunk будет эквивалентен функции, возвращающей значение value. 9. Вернуть ? Invoke(promise, "then", « valueThunk »).
Свойство «length» функции «Then Finally» равно 1.
Catch Finally Functions
Функция «Catch Finally» — это анонимная встроенная функция, которая имеет внутренний слот [[Constructor]] и [[OnFinally]]. Значение внутреннего слота [[Constructor]] — это объект функции конструктора, подобный Promise, а значение внутреннего слота [[OnFinally]] — это объект функции.
Когда функция «Catch Finally» вызывается с аргументом reason, выполняются следующие шаги:
1. Пусть F будет активным функциональным объектом. 2. Пусть onFinally будет F.[[OnFinally]]. 3. Утверждение: IsCallable(onFinally) является истиной true. 4. Пусть result будет ? вызов Call(onFinally, undefined). 5. Пусть C будет F.[[Constructor]]. 6. Утверждение: IsConstructor(C) является истиной true. 7. Пусть promise будет ? PromiseResolve(C, result). 8. Пусть метатель thrower будет эквивалентен функции, которая бросает причину reason. 9. Вернуть ? Invoke(promise, "then", « thrower »).
Promise.prototype.then ( onFulfilled, onRejected )
Когда метод then вызывается с аргументами onFulfilled и onRejected, выполняются следующие шаги:
1. Пусть обещание promise будет значением this. 2. Если IsPromise(promise) является ложным false, выбросить исключение TypeError. 3. Пусть C будет ? SpeciesConstructor(promise, %Promise%). 4. Пусть resultCapability будет ? NewPromiseCapability(C). 5. Вернуть PerformPromiseThen(promise, onFulfilled, onRejected, resultCapability).
PerformPromiseThen ( promise, onFulfilled, onRejected [ , resultCapability ] )
Абстрактная операция «PerformPromiseThen» принимает аргументы promise, onFulfilled, и onRejected, а также необязательный аргумент resultCapability (запись PromiseCapability Record). Он выполняет операцию «затем»(then) для обещания promise, используя onFulfilled и onRejected в качестве расчетных действий. Если передается resultCapability, результат сохраняется путем обновления обещания от resultCapability. Если он не передан, то «PerformPromiseThen» вызывается внутренней операцией спецификации, результат которой не имеет значения. При вызове он выполняет следующие шаги:
1. Утверждение: IsPromise(promise) является истиной true. 2. Если resultCapability отсутствует (не представлен), то 1. Установите для resultCapability значение undefined. 3. Если IsCallable(onFulfilled) является ложью false, то 1. Пусть onFulfilledJobCallback будет пустым - "empty". 4. Иначе, 1. Пусть onFulfilledJobCallback будет HostMakeJobCallback(onFulfilled). 5. Если IsCallable(onRejected) является ложью false, то 1. Пусть onRejectedJobCallback будет "empty". 6. Иначе, 1. Пусть onRejectedJobCallback будет HostMakeJobCallback(onRejected). 7. Пусть fulfillReaction будет PromiseReaction { [[Capability]]: resultCapability, [[Type]]: Fulfill, [[Handler]]: onFulfilledJobCallback }. 8. Пусть rejectReaction будет PromiseReaction { [[Capability]]: resultCapability, [[Type]]: Reject, [[Handler]]: onRejectedJobCallback }. 9. Если promise.[[PromiseState]] является pending, тогда 1. Добавьте fillReaction в качестве последнего элемента списка List, который является promise.[[PromiseFulfillReactions]]. 2. Добавьте rejectReaction в качестве последнего элемента списка List, который является promise.[[PromiseRejectReactions]]. 10. Иначе, если promise.[[PromiseState]] является выполненным fulfilled, то 1. Пусть значение value будет promise.[[PromiseResult]]. 2. Пусть fulfillJob будет NewPromiseReactionJob(fulfillReaction, value). 3. Выполните HostEnqueuePromiseJob(fulfillJob.[[Job]], fulfillJob.[[Realm]]). 11. Иначе, 1. Утверждение: значение promise.[[PromiseState]] является rejected. 2. Пусть причина reason будет promise.[[PromiseResult]]. 3. Если promise.[[PromiseIsHandled]] является ложью false, выполните HostPromiseRejectionTracker(promise, "handle"). 4. Пусть rejectJob будет NewPromiseReactionJob(rejectReaction, reason). 5. Выполните HostEnqueuePromiseJob(rejectJob.[[Job]], rejectJob.[[Realm]]). 12. Установите для promise.[[PromiseIsHandled]] значение true. 13. Если resultCapability является undefined, то 1. Вернуть undefined. 14. Иначе, 1. Вернуть resultCapability.[[Promise]].
Promise.prototype [ @@toStringTag ]
Начальным значением свойства @@toStringTag является строковое значение «Promise«.
Это свойство имеет атрибуты { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.
Свойства экземпляров Обещания
Экземпляры Обещаний (Promise Instances) — это обычные объекты, которые наследуют свойства от объекта-прототипа Promise (встроенный, %Promise.prototype%). Экземпляры обещаний изначально создаются с использованием внутренних слотов, описанных в Таблице 79.
Внутренний слот (Internal Slot) | Описание (Description) |
[[PromiseState]] | Один из: ожидает (pending), выполнен (fulfilled) или отклонён (rejected). Управляет тем, как Обещание будет реагировать на входящие вызовы его метода then(). |
[[PromiseResult]] | Значение, с которым Обещание было выполнено (fulfilled) или отклонено (rejected), если таковое имеется. Имеет значение, только если [[PromiseState]] не ожидает обработки (pending). |
[[PromiseFulfillReactions]] | Список записей PromiseReaction, которые будут обрабатываться, когда / если обещание переходит из состояния ожидания (pending) в состояние выполнения (fulfilled). |
[[PromiseRejectReactions]] | Список записей PromiseReaction, которые будут обрабатываться, когда / если обещание переходит из состояния ожидания (pending) в состояние отклонения (rejected). |
[[PromiseIsHandled]] | Логическое значение, указывающее, был ли у Обещания когда-либо обработчик (handler) выполнения или отклонения; используется в отслеживании необработанных отклонений. |
Таблица 79: Внутренние слоты экземпляров Promise
Ссылки
Официальный стандарт ECMAScript — «Promise Objects» — https://tc39.es/ecma262/#sec-promise-objects