Нет, это не значит, что работать синхронно
async
и await
являются "синтаксическим сахаром" для Promise
, как было установлено. Это означает, что синтаксис эквивалентен следующему в ES2015 и ES2016, при выполнении функции генератора в качестве сопрограммы (после исправления синтаксических ошибок в вашем примере)
someReceiveACallback('event', function() {
return coroutine(function*() {
const result = yield imAsync(); /*1*/
let anotherResult = null; /*2*/
if (result.authenticated)
anotherResult = yield imAlsoAsync(); /*3*/
send(anotherResult); /*4*/
}).apply(this, arguments);
});
function coroutine(fn) {
return function() {
return new Promise((resolve, reject) => {
const gen = fn.apply(this, arguments);
const step = method => result => {
try { var { value, done } = gen[method](result); }
catch (error) { reject(error); return; }
if (done) { resolve(value); }
else { Promise.resolve(value).then(_next, _throw); }
};
const _next = step('next');
const _throw = step('throw');
_next(undefined);
});
};
}
Исходный код, сгенерированный babel
Проще говоря, только все до первого встреченного выражения await
выполняется синхронно. Это связано с вызовом _next(undefined)
в исполнителе конструктора Promise
.
После этого функция возвращает обещание вызывающей стороне, которое устанавливается, когда выполнение функции достигает конца своего потока управления.
Каждый блок между последовательно встречающимися await
выражениями выполняется внутри собственного асинхронного продолжения .then(...)
.
Цель сопрограммы - запустить процедуру разрешения обещания для каждого выражения yield
, обнаруженного в генераторе. Когда обещание выполнено, сопрограмма асинхронно повторно входит в поток управления в той же точке, предоставляя разрешенное значение или выбрасывая отклоненную причину. Promise.resolve(value).then(_next, _throw)
это то, что делает.
При встроенной поддержке async
/ await
все, что делает coroutine()
, фактически реализовано в цикле событий среды выполнения.