Обратный вызов конструктора Promise выполняется асинхронно?
Предположим, что у меня этот код
function y(resolve, reject)
{
console.log("Result");
resolve();
}
var promise = new Promise(y);
Что я хочу знать, будет ли функция y
выполняться асинхронно или нет.
Ответы
Ответ 1
Это зависит от реализации обещания. Если мы проверим спецификацию. Вы можете найти окончательный spec здесь - так как этот ответ был изначально написан, он был доработан.
Вот соответствующий отрывок (вы можете найти исходный источник здесь)
- Пусть завершение будет Call (исполнитель, undefined, "resolvingFunctions. [[Resolve]], resolvingFunctions. [[Reject]]" ).
- Если завершение является резким завершением, то
- Разрешить статус Call (разрешать функции. [[Отклонить]], undefined, "завершить. [[значение]]" ).
- ReturnIfAbrupt (статус).
Стандарт ES6 указывает, что выполнение обещания всегда асинхронно (см. раздел 25.4.5.3, Promise.prototype.then
и сопровождающий раздел 25.4.5.3.1, PerformPromiseThen
). Я разместил соответствующий материал ниже.
PerformPromiseThen
- Иначе, если значение слота [[PromiseState]] обещания "выполнено",
- Значение value является обязательным словом [[PromiseResult]].
- Выполняйте EnqueueJob ( "PromiseJobs", PromiseReactionJob, "performReaction, value" ).
- Если значение обещания [[PromiseState]] внутреннего слота "отклонено",
- Пусть разум будет значением внутреннего слота [[PromiseResult]].
- Выполните EnqueueJob ( "PromiseJobs", PromiseReactionJob, "rejectReaction, reason" ).
TL;DR: функция, переданная в обещание, выполняется синхронно, но последующие вызовы then
всегда выполняются асинхронно.
Ответ 2
Другой ответ доказывает это, но позвольте мне рассказать о причинах:
Конструктор Promise
Обратный вызов конструктора обещаний (как указано в спецификации ES6 или в библиотеках спецификаций конструктора) всегда будет выполняться синхронно - это делается для того, чтобы извлечь из него отложенную (более старую форму построения обещания) на случай, если вам понадобится доступ на обратный вызов resolve
:
var r;
var p new Promise(function(resolve, reject){
r = resolve;
});
// use r here, for example
arr.push(r);
then
обратные вызовы
then
всегда будет выполняться асинхронно, практически все основные реализации обещаний (Native, Bluebird, $ q, Q, когда, rsvp, обещание, jQuery (с версии 3.0) и т.д.), А также нативные обещания реализуют (или реализуют расширенный набор (с дополнительными ограничениями) Обещания /A+.
Именно поэтому Promises/A+ был создан из Promises/A. Асинхронные гарантии будут сохранены, а Zalgo не будет выпущен. (Также см. этот пост).
Тот факт, что это происходит (асинхронная гарантия), является полностью преднамеренным и активно предотвращает условия гонки. Код in- и вне then
всегда будет выполняться в одном и том же порядке.
Вот соответствующая цитата:
onFulfilled
или onRejected
не должны вызываться, пока стек контекста выполнения не содержит только код платформы. [3,1].