Передается ли функция разрешения исполнителю обещания асинхронно?

avatar
Natalia Cherniavskaia
8 августа 2021 в 20:20
97
1
4

У меня есть следующий код:

function myPromiseFunc() {
  return new Promise((resolve) => {
    resolve(Promise.resolve(123));
  });
}

Как мы знаем, метод Promise.resolve немедленно разрешает Promise с простым значением. Итак, Promise.resolve(123) -> Promise<fulfilled> Но:

console.log(myPromiseFunc());

вернет Promise со статусом pending. Почему? Функция разрешения передается исполнителю асинхронно? Причина:

setTimeout(console.log, 0, res);

вернет Promise<fulfilled>.

Я знаю, что Promises используют микрозадачи, но он должен использоваться только для обработчиков.

Promises/A+ говорит:

[[Resolve]](обещание, x) -> If/when x is a promise and fulfilled, fulfill promise with the same value.

Кстати. Этот фрагмент вернет Promise<fulfilled>:

function myPromiseFunc() {
  return new Promise((resolve) => {
    resolve(123);
  });
}

Похоже, что resolve является асинхронным только тогда, когда Promise передается как значение.

Пожалуйста, помогите разобраться. Спасибо!

Источник
Natalia Cherniavskaia
8 августа 2021 в 20:24
0

@evolutionxbox Я знаю. Это просто теоретический вопрос. Почему у меня статус pending вместо fulfilled?

evolutionxbox
8 августа 2021 в 20:25
0

Используйте myPromiseFunc().then(console.log), чтобы увидеть разрешенный вывод.

Natalia Cherniavskaia
8 августа 2021 в 20:29
0

Я не хочу видеть разрешенный вывод :) Я хочу понять, меняют ли обещания свои статусы асинхронно или что происходит

Ответы (1)

avatar
Kelvin Schoofs
8 августа 2021 в 20:38
3

Согласно спецификации функции resolve, переданной исполнителю в new Promise((resolve, reject) => ...):

Когда функция разрешения промисов вызывается с аргументом resolution, выполняются следующие шаги:

  1. Пусть F будет активным функциональным объектом.
  2. Утверждение: F имеет внутренний слот [[Promise]], значение которого является объектом.
  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) не является объектом, то
    1. Возврат FulfillPromise(promise, resolution).
  9. Пусть then будет Get(resolution, "then").
  10. Если 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.

Много технического жаргона, но самое главное в вашем вопросе заключается в том, что resolution — это значение, которое вы ему передали. Если это (примерно) не обещание, вы окажетесь либо в 8.1 (для не-объектов), либо в 12.1 (для невызываемых объектов), которые сразу же выполнят обещание. Если вы передали значение с помощью функции then (например, обещание), оно выполнит все шаги, начиная с 13, где оно в основном ставит в очередь .then и следует за всем «мое выполнение зависит от выполнения другого обещания». ".

Natalia Cherniavskaia
8 августа 2021 в 20:57
0

Это удивительно! Благодарю вас! Я просмотрел спецификацию, но не понял.

ikhvjs
9 августа 2021 в 07:34
0

Хорошее объяснение. Поправьте меня, если я ошибаюсь. Это означает, что resolve не передается функции в асинхронном режиме, но зависит от аргумента, который вы передаете resolve, чтобы определить, что произойдет дальше.

Kelvin Schoofs
9 августа 2021 в 08:02
0

Вызов resolve немедленно выполнит обещание (если только вы не вызовете его с другим обещанием, в этом случае вызов .then ставится в очередь, то есть шаг 13+). Исполнитель, как и в функции, которую вы передаете new Promise(...), вызывается немедленно (синхронно). Но да, в зависимости от значения, переданного resolve, это будет либо «выполнить немедленно», либо «поставить в очередь .then».