Я пытался связать две асинхронные функции вместе, потому что первая имела параметр условного возврата, из-за которого вторая либо запускалась, либо выходила из модуля. Однако я обнаружил странное поведение, которое не смог найти в спецификациях.
async function isInLobby() {
//promise.all([chained methods here])
let exit = false;
if (someCondition) exit = true;
}
Это убогий фрагмент моего кода (вы можете увидеть полный объем здесь ), который просто проверяет, находится ли игрок в лобби, но это не имеет значения.
Далее у нас есть асинхронная функция.
async function countPlayer() {
const keyLength = await scardAsync(game);
return keyLength;
}
Эту функцию не нужно запускать, если exit === true
.
Я пытался сделать
const inLobby = await isInLobby();
Я надеялся, что это будет ждать результатов, поэтому я могу использовать inLobby
для условного запуска countPlayer
, однако я получил ошибку типа без каких-либо конкретных деталей.
Почему вы не можете await
выполнить async
функцию за пределами функции? Я знаю, что это сахарное обещание, поэтому оно должно быть привязано к нему, then
но почему внутри countPlayer
я могу ждать другого обещания, а снаружи я не могу await
isInLobby
?
источник
await isInLobby()
и какinLobby
используется? Кроме того, где / какcountPlayer
называется?isInLobby().then( … countPlayer().then …
части, решение тривиально: просто создайте функцию, в которой содержатся эти вызовы (ту(req, res) =>
)async
.await
? Вот почему я подумал, что вы приняли ответ, который на самом деле не имеет отношения к проблеме в вопросе.Ответы:
Верхний уровень
await
не поддерживается. В комитете по стандартам есть несколько дискуссий о том, почему это так, например, этот вопрос Github .На Github также есть статья о том, почему ожидание верхнего уровня - плохая идея. В частности, он предполагает, что если у вас есть такой код:
// data.js const data = await fetch( '/data.json' ); export default data;
Теперь любой импортируемый файл
data.js
не будет выполняться до завершения выборки, поэтому вся загрузка вашего модуля теперь заблокирована. Из-за этого очень сложно рассуждать о порядке модулей приложения, поскольку мы привыкли, что Javascript верхнего уровня выполняется синхронно и предсказуемо. Если бы это было разрешено, узнать, когда функция будет определена, будет сложно.Я считаю , что для вашего модуля плохая практика - иметь побочные эффекты, просто загружая его. Это означает, что любой потребитель вашего модуля получит побочные эффекты, просто потребовав ваш модуль. Это сильно ограничивает возможности использования вашего модуля. Верхний уровень,
await
вероятно, означает, что вы читаете какой-либо API или вызываете какой-либо сервис во время загрузки. Вместо этого вам следует просто экспортировать асинхронные функции, которые потребители могут использовать в своем собственном темпе.источник
void async function() { const inLobby = await isInLobby() }()
inLobby
функция недоступна для функции?.then()
(извините, я должен был прояснить это).Конечно, всегда есть это:
(async () => { await ... // all of the script.... })(); // nothing else
Это обеспечивает быструю работу с async, где вы можете использовать ожидание. Это избавляет вас от необходимости создавать асинхронную функцию, и это здорово! // кредиты Silve2611
источник
await
эта анонимная функция, которая, опять же, не работает извне функций.Еще лучше поставить дополнительную точку с запятой перед блоком кода
;(async () => { await ... })();
Это не позволяет автоматическому форматированию (например, в vscode) перемещать первую круглую скобку в конец предыдущей строки.
Проблема может быть продемонстрирована на следующем примере:
const add = x => y => x+y const increment = add(1) (async () => { await ... })();
Без точки с запятой это будет переформатировано как:
const add = x => y => x+y const increment = add(1)(async () => { await Promise(1) })()
что, очевидно, неверно, потому что он назначает асинхронную функцию в качестве
y
параметра и пытается вызвать функцию из результата (который на самом деле является странной строкой'1async () => {...}'
)источник
add(1);
а не перед функцией async.Начиная с Node.js 14.3.0, поддерживается ожидание верхнего уровня.
Обязательный флаг:
--experimental-top-level-await
.Дополнительная информация: https://v8.dev/features/top-level-await
источник
вы можете выполнить ожидание верхнего уровня, так как typescript 3.8
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#-top-level-await
Из сообщения:
Это потому, что ранее в В JavaScript (как и в большинстве других языков с аналогичной функцией) ожидание было разрешено только в теле асинхронной функции. Однако с ожиданием верхнего уровня мы можем использовать ожидание на верхнем уровне модуля.
const response = await fetch("..."); const greeting = await response.text(); console.log(greeting); // Make sure we're a module export {};
Обратите внимание на тонкость: await верхнего уровня работает только на верхнем уровне модуля, а файлы считаются модулями только тогда, когда TypeScript находит импорт или экспорт. В некоторых базовых случаях вам может потребоваться написать export {} в качестве шаблона, чтобы убедиться в этом.
Ожидание верхнего уровня может работать не во всех средах, в которых вы могли ожидать на этом этапе. В настоящее время вы можете использовать ожидание верхнего уровня только тогда, когда целевой параметр компилятора - es2017 или выше, а модуль - esnext или system. Поддержка в нескольких средах и сборщиках может быть ограничена или может потребоваться включение экспериментальной поддержки.
источник