Обратный вызов конструктора Promise выполняется асинхронно?

Предположим, что у меня этот код

function y(resolve, reject)
{
  console.log("Result");
  resolve();
}  

var promise = new Promise(y);

Что я хочу знать, будет ли функция y выполняться асинхронно или нет.

Ответ 1

Это зависит от реализации обещания. Если мы проверим спецификацию. Вы можете найти окончательный spec здесь - так как этот ответ был изначально написан, он был доработан.

Вот соответствующий отрывок (вы можете найти исходный источник здесь)

  1. Пусть завершение будет Call (исполнитель, undefined, "resolvingFunctions. [[Resolve]], resolvingFunctions. [[Reject]]" ).
  2. Если завершение является резким завершением, то
    • Разрешить статус Call (разрешать функции. [[Отклонить]], undefined, "завершить. [[значение]]" ).
    • ReturnIfAbrupt (статус).

Стандарт ES6 указывает, что выполнение обещания всегда асинхронно (см. раздел 25.4.5.3, Promise.prototype.then и сопровождающий раздел 25.4.5.3.1, PerformPromiseThen). Я разместил соответствующий материал ниже.

PerformPromiseThen

  1. Иначе, если значение слота [[PromiseState]] обещания "выполнено",
    • Значение value является обязательным словом [[PromiseResult]].
    • Выполняйте EnqueueJob ( "PromiseJobs", PromiseReactionJob, "performReaction, value" ).
  2. Если значение обещания [[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].