如果当前运行时支持,则使用顶级等待
Use a top-level await, if supported by the current runtime
顶级等待支持已通过 --experimental-top-level-await
添加到 14.3.0 中的 Node.js,后来添加到 --harmony-top-level-await
。
问题
如果当前 Node.js 运行时支持,我需要在我的 ESM 脚本文件中使用顶级等待。此外,我需要设置一个布尔标志来指示在顶层成功等待了承诺。
我的意思的一个例子:
let topLevelAwaitEnabled;
try {
await Promise.resolve(); // replaced with an actual promise
topLevelAwaitEnabled = true;
} catch (ignored) {
topLevelAwaitEnabled = false;
}
console.log(topLevelAwaitEnabled);
// carry on with the rest of the application, regardless of success or failure
// at some point, topLevelAwaitEnabled is checked to conditionally execute some code
如果启用顶级等待支持,这会成功。 但是,如果不支持,这会导致解析时出现如下错误,无法在运行时 与 try
/catch
:
$ node test.js...\test.js:3
await Promise.resolve(); // replaced with an actual promise
^^^^^
SyntaxError: await is only valid in async function
所以问题是:如何使用顶层 await if 它受支持,而不会与不支持顶层的 Node.js 运行时产生不兼容问题await(没有指定 CLI 标志或根本没有运行时支持)?
如果答案是“不可能”,我想解释为什么这是不可能的。
在我实际提交 XY problem 的情况下,根本问题是我需要顶级动态导入。
Note: I am well aware that top level await is not recommended for a variety of reasons, however it is crucial for a specific functionality of my application and does not impose any issue with my use case. Alternatives will likely not suffice.
尝试次数
我尝试了以下方法,没有用:
eval
:我尝试用 eval("await Promise.resolve()")
替换等待行,希望代码在当前上下文中被评估。不幸的是,即使支持顶级等待,这也会导致相同的错误,因为它似乎没有继承当前上下文。
vm.compileFunction
:同样的问题 eval()
,不支持顶级等待。
vm.SourceTextModule
:评估是异步的,需要在顶层等待以检查它是否受支持……这是一个陷阱 22。
- 基于
process.version
和process.execArgv
的await
条件执行:解析期间的错误-它从未实际执行代码,因此排除了条件执行。
似乎您可以像这样检查运行时使用的节点版本 process.version
然后您还可以使用 process.argv
检查启动时传入的任何标志过程。
使用上述方法,您可以先检查正在使用的节点版本,然后如果相关,您可以检查所需的标志。
节点 docs 检查 CLI 参数。
(async()=>{await promise})()
据我所知这是不可能的,因为解析器只会出错。编译器不会理解 await
指令,也不会完成它的循环。这可能类似于使用根本不是可识别关键字的词。
最接近的是使用匿名函数。
顶级等待支持已通过 --experimental-top-level-await
添加到 14.3.0 中的 Node.js,后来添加到 --harmony-top-level-await
。
问题
如果当前 Node.js 运行时支持,我需要在我的 ESM 脚本文件中使用顶级等待。此外,我需要设置一个布尔标志来指示在顶层成功等待了承诺。
我的意思的一个例子:
let topLevelAwaitEnabled;
try {
await Promise.resolve(); // replaced with an actual promise
topLevelAwaitEnabled = true;
} catch (ignored) {
topLevelAwaitEnabled = false;
}
console.log(topLevelAwaitEnabled);
// carry on with the rest of the application, regardless of success or failure
// at some point, topLevelAwaitEnabled is checked to conditionally execute some code
如果启用顶级等待支持,这会成功。 但是,如果不支持,这会导致解析时出现如下错误,无法在运行时 与 try
/catch
:
$ node test.js...\test.js:3
await Promise.resolve(); // replaced with an actual promise
^^^^^
SyntaxError: await is only valid in async function
所以问题是:如何使用顶层 await if 它受支持,而不会与不支持顶层的 Node.js 运行时产生不兼容问题await(没有指定 CLI 标志或根本没有运行时支持)?
如果答案是“不可能”,我想解释为什么这是不可能的。
在我实际提交 XY problem 的情况下,根本问题是我需要顶级动态导入。
Note: I am well aware that top level await is not recommended for a variety of reasons, however it is crucial for a specific functionality of my application and does not impose any issue with my use case. Alternatives will likely not suffice.
尝试次数
我尝试了以下方法,没有用:
eval
:我尝试用eval("await Promise.resolve()")
替换等待行,希望代码在当前上下文中被评估。不幸的是,即使支持顶级等待,这也会导致相同的错误,因为它似乎没有继承当前上下文。vm.compileFunction
:同样的问题eval()
,不支持顶级等待。vm.SourceTextModule
:评估是异步的,需要在顶层等待以检查它是否受支持……这是一个陷阱 22。- 基于
process.version
和process.execArgv
的await
条件执行:解析期间的错误-它从未实际执行代码,因此排除了条件执行。
似乎您可以像这样检查运行时使用的节点版本 process.version
然后您还可以使用 process.argv
检查启动时传入的任何标志过程。
使用上述方法,您可以先检查正在使用的节点版本,然后如果相关,您可以检查所需的标志。
节点 docs 检查 CLI 参数。
(async()=>{await promise})()
据我所知这是不可能的,因为解析器只会出错。编译器不会理解 await
指令,也不会完成它的循环。这可能类似于使用根本不是可识别关键字的词。
最接近的是使用匿名函数。