Где в спецификации ECMAScript указано возвращаемое значение из выражения await? - PullRequest
0 голосов
/ 09 ноября 2019

Недавно я попытался выяснить, как работают обещания в ECMAScript. Больше всего интересует конструкция AwaitExpression. На мой взгляд, это самое непонятное и довольно сложное в спецификации.

Позвольте мне привести код:

    /// Promise
    var promiseA = new Promise((resolve, reject) => {
        setTimeout(() => resolve("Done!"), 10000)
      });
    /// Async/Await
    (async function(){
        var result = await promiseA;
        console.log(result); /// Output: "Done!"
    })();
    /// Promise.prototype.then
    promiseA.then(function (result){
        console.log(result); /// Output: "Done!"
    });

Для меня, как я уже сказал выше, AwaitExpression непостижимо, я не понимаю, куда идет возврат значения из обещания. Но я понимаю, откуда берется значение из [[PromiseResult]] и как значение [[PromiseResult]] из .then передается в аргумент функции обратного вызова.

И есть некоторые шаги, которые, к сожалению,мне не понятно от Await () :

Удалите asyncContext из стека контекста выполнения и восстановите контекст выполнения, находящийся на вершине стека контекста выполнения, в качестве контекста выполнения выполнения. Установите состояние оценки кода asyncContext таким образом, чтобы при возобновлении оценкис завершением Завершения будут выполнены следующие шаги алгоритма, который вызвал Await, с доступным завершением. Возврат. ПРИМЕЧАНИЕ: Это возвращает к оценке операции, которая имела место ранееВозобновленная оценка asyncContext.

И часть действий из Ожидающих выполненных функций все еще не совсем ясна:

Возобновить приостановленную оценку asyncContext, используя NormalCompletion (значение) в результате операции, которая приостановила его. Утверждение: Когда мы достигаем этого шага, asyncContext уже был удален из стека контекста выполнения и prevContextявляется текущим контекстом выполнения. Возврат не определен.

PS Как выполняются Promise и .then ясномне, вы можете принять это во внимание при объяснении AwaitExpression.

Ответы [ 2 ]

2 голосов
/ 09 ноября 2019

Я думаю, что при чтении важно помнить, что спецификация может свободно запускать и останавливать выполнение данной функции прямо посередине. Когда это происходит, функция буквально останавливается именно там, где она есть, но шаги spec продолжают выполняться.

Учитывая ваш пример

(async function(){
  var result = await promiseA;
  console.log(result); /// Output: "Done!"
})();

в терминах спецификации, эта функциястановится:

  1. Вызовите асинхронную функцию [[Call]]
    1. Выполните обычную подготовительную работу для этой функции
    2. OrdinaryCallEvaluateBody
      1. EvaluateBody для асинхронных функций
        1. Создать обещание, возвращаемое асинхронной функцией
        2. AsyncFunctionStart
          1. Инициализировать возвращаемый объект обещания
          2. Пометить контекст выполнения таким образом, чтобы, когда он полностью завершится, он выполнил или отклонил обещание.
          3. Начните выполнениепошаговые шаги функции
            1. В конечном итоге мы получаем await и делаем:
            2. Используя ожидаемое обещание, установите его так, чтобы асинхронныйфункция возобновит выполнение после завершения обещания. (Шаг 2-9)
            3. «вывести контекст выполнения», который отмечает, какой шаг мы выполняли в функции, чтобы его можно было запустить позже. (Шаг 10 в вашей цитате)
            4. Установите флаг в контексте выполнения, говоря, что «функция приостановлена, когда она возобновится, вы получите результат обещания, пожалуйста, возобновите функцию, как если бы результат обещания былзначение завершения 'await'. (Шаг 11)
            5. Return. (Шаг 12).
        3. Возвращает обещание для асинхронногоfn result.

Главное, что нужно понять, это то, что шаг 12 не возвращается в асинхронную функцию, потому что он был приостановлен. Он возвращается к AsyncFunctionStart, который затем возвращается к EvaluateBody, который затем возвращает результат Promise асинхронной функции.

Затем, позже, когда promiseAвыполняет (из-за работы с шагами 2-9 ранее)

  1. Установите асинхронную функцию снова в качестве активного контекста выполнения ( Шаг 5 из «Ожидание выполненных функций» )
  2. Возобновить выполнение с результатом обещания как «завершение» (Шаг 6). Флаги, установленные на шаге 11, используют значение завершения в качестве результата ожидания и фиксируют выполнение асинхронной функции до тех пор, пока она не вернется или не ждет снова.
  3. Утверждение, что асинхронная функция завершила некоторую работуна данный момент (Шаг 7)
  4. Return. (Шаг 8)
2 голосов
/ 09 ноября 2019

Это часть

, использующая NormalCompletion(value) в результате операции, которая приостановила ее.

из цитируемого вами текста. Он возобновит выполнение async function и заставит выражение await иметь value в качестве результата. Сравните операцию yield и метод генератора next() для справки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...