Я перебирал async
/ await
после того, как просмотрел несколько статей, я решил проверить себя сам. Тем не менее, я не могу обернуться, почему это не работает:
async function main() {
var value = await Promise.resolve('Hey there');
console.log('inside: ' + value);
return value;
}
var text = main();
console.log('outside: ' + text);
Консоль выводит следующее (узел v8.6.0):
> снаружи: [обещание объекта]
> Внутри: Привет
Почему сообщение журнала внутри функции выполняется позже? Я думал, что причина async
/ await
была создана для того, чтобы выполнить синхронное выполнение с использованием асинхронных задач.
Есть ли способ я могу использовать значение, возвращенное внутри функции без использования .then()
после main()
?
await
ничего, кроме сахара дляthen
синтаксиса обещания .main
async/await
является частью ES2017, а не ES7 (ES2016)Ответы:
Потому что
main
возвращает обещание; всеasync
функции делают.На верхнем уровне вы должны либо:
Используйте функцию верхнего уровня,
async
которая никогда не отклоняет (если вы не хотите ошибок «необработанного отклонения»), илиИспользуйте
then
иcatch
, или(Скоро!) Используйте верхнего уровня
await
, предложение, достигшее стадии 3 в процессе, который позволяет использование верхнего уровняawait
в модуле.# 1 -
async
функция верхнего уровня, которая никогда не отклоняетОбратите внимание на
catch
; вы должны обрабатывать обещания отклонения / асинхронные исключения, так как больше ничего не происходит; у вас нет звонящего, чтобы передать их. Если вы предпочитаете, вы можете сделать это в результате вызова черезcatch
функцию (вместоtry
/catch
синтаксис):... что немного более кратко (мне нравится по этой причине).
Или, конечно, не обрабатывать ошибки, а просто допустить ошибку «необработанное отклонение».
№ 2 -
then
иcatch
catch
Обработчик будет вызываться при возникновении ошибок в цепи или вthen
обработчике. (Убедитесь, что вашcatch
обработчик не генерирует ошибки, так как ничего не зарегистрировано для их обработки.)Или оба аргумента
then
:Снова обратите внимание, что мы регистрируем обработчик отклонения. Но в этой форме, будьте уверены, что ни один из ваших
then
обратных вызовов не выдает никаких ошибок, ничего не зарегистрировано для их обработки.# 3 верхнего уровня
await
в модулеВы не можете использовать
await
на верхнем уровне скрипта без модуля, но на высшем уровнеawait
предложение ( этап 3 ) позволяет использовать его на верхнем уровне модуля. Это похоже на использованиеasync
оболочки функций верхнего уровня (# 1 выше) в том смысле, что вы не хотите, чтобы ваш код верхнего уровня отклонял (выдавал ошибку), потому что это приведет к необработанной ошибке отклонения. Поэтому, если вы не хотите иметь необработанное отклонение, когда что-то пойдет не так, как в случае с # 1, вы захотите обернуть свой код в обработчик ошибок:Обратите внимание, что если вы сделаете это, любой модуль, который импортирует из вашего модуля, будет ждать, пока не выполнится обещание
await
; когда модуль, использующий верхний уровеньawait
, оценивается, он в основном возвращает обещание загрузчику модулей (как этоasync
делает функция), которое ждет, пока это обещание не будет выполнено, прежде чем оценивать тела любых модулей, которые зависят от него.источник
async
/await
являются синтаксическим сахаром вокруг обещаний (хороший вид сахара :-)). Вы не просто думаете об этом как о возвращении обещания; это действительно так. ( Подробности .)async
опцией all- first. Для функции верхнего уровня я могу видеть это в любом случае (в основном из-за двух уровней отступа вasync
версии).await
достигло стадии 3. :-)Верхний уровень
await
перешел на этап 3, поэтому ответ на ваш вопрос Как я могу использовать async / await на верхнем уровне? это просто добавитьawait
вызов кmain()
:Или просто:
Имейте в виду, что он по-прежнему доступен только в Webpack@v5.0.0-alpha.15 .
Если вы используете TypeScript , он появился в 3.8 .
В версии 8 добавлена поддержка модулей.
Это также поддерживается Дено (как прокомментировал Гонсало-Бахамондез).
источник
Фактическое решение этой проблемы заключается в том, чтобы подойти к ней по-другому.
Возможно, вашей целью является какая-то инициализация, которая обычно происходит на верхнем уровне приложения.
Решение состоит в том, чтобы на верхнем уровне вашего приложения был только один единственный оператор JavaScript. Если у вас есть только один оператор в верхней части вашего приложения, тогда вы можете свободно использовать async / await в любой другой точке в любом месте (при условии, конечно, нормальных правил синтаксиса)
Другими словами, оберните весь верхний уровень в функцию так, чтобы он больше не был верхним, и это решает вопрос о том, как запустить async / await на верхнем уровне приложения, а вы - нет.
Вот как должен выглядеть верхний уровень вашего приложения:
источник
application()
быть асинхронным?Чтобы дать некоторую дополнительную информацию поверх текущих ответов:
Содержимое
node.js
файла в настоящее время объединяется в виде строки, чтобы сформировать тело функции.Например, если у вас есть файл
test.js
:Затем
node.js
тайно объединит функцию, которая выглядит следующим образом:Главное, что следует отметить, это то, что результирующая функция НЕ является асинхронной функцией. Таким образом, вы не можете использовать термин
await
непосредственно внутри него!Но скажем, вам нужно работать с обещаниями в этом файле, тогда есть два возможных метода:
await
непосредственно внутри функцииawait
Вариант 1 требует, чтобы мы создали новую область (и ЭТА область может быть
async
, потому что у нас есть контроль над ней):Вариант 2 требует от нас использования объектно-ориентированного API обещаний (менее привлекательная, но в равной степени функциональная парадигма работы с обещаниями)
Лично я надеюсь, что, если это работает, node.js по умолчанию объединит код в
async
функцию. Это избавило бы от этой головной боли.источник
Ожидание верхнего уровня - это особенность грядущего стандарта EcmaScript. В настоящее время вы можете начать использовать его с TypeScript 3.8 (в настоящее время в версии RC).
Как установить TypeScript 3.8
Вы можете начать использовать TypeScript 3.8, установив его из npm, используя следующую команду:
В настоящее время вам необходимо добавить
rc
тег для установки последней версии 3.8.источник
Поскольку
main()
работает асинхронно, он возвращает обещание. Вы должны получить результат вthen()
методе. И потому чтоthen()
обещание возврата тоже, вы должны позвонить,process.exit()
чтобы закончить программу.источник
exit()
чтобы сообщить, произошла ли ошибка.process.exit(1)