JavaScript / Node.js 如何在模块顶层使用 await

5

我尝试找到解决我的问题的方法,但是没能找到,所以我正在寻找一些"最佳实践示例"。我有一个Node.js Express应用程序,我的函数被拆分成文件。例如,我有这个控制器(oktacontroller.js):

var okta_api_key = <here some await data, getting from db>;

const OKTA_ORG_URL = '<here too>';

exports.createUser = async (req, res) => {

    console.log(okta_api_key);
}

exports.getGroups = async (req, res) => {
    console.log(okta_api_key);
}

在这两个导出的函数中(它们是Express路由),我需要变量okta_api_key。 我知道我可以通过在两个函数中查询它们来获取它们,因为它们是异步函数,我可以在那里使用await,但是每次查询这个变量都感觉很愚蠢(因为它永远不会改变)。

我该如何处理? 我知道可以这样做:

var okta_api_key;
(async () => {
    okta_api_key = await <getting key async>
})()

但是这种感觉也不太对...

有没有办法创建一个异步的大函数,并导出这两个函数?换句话说:如何在文件(模块)顶层使用await。它不一定需要在顶层(这是不可能的),但我需要一些方法将我的“顶层”变量暴露给我的导出函数。

编辑:因为我得到了将其放入配置文件中的建议,所以还有其他用例。对于这个用例,是可能的,但是例如:我有一些其他的API密钥,它从服务本身获取访问令牌,在每次启动时(因为它会过期)。该令牌不能存储在配置文件中,因此我需要一些异步工作来获取该值。我知道顶级等待不起作用(甚至不可取),但如果这是您的项目,我只想要一个示例来展示您们如何实现此操作:)


2
目前还不行,它仍然是一个第二阶段提案,我建议先阅读这篇文章:顶层等待是一种危险的做法 - zero298
2
如果它从不改变,为什么需要存储在数据库中?只需将其放入配置文件中并将其导入到您的模块中即可。 - Isaac Vidrine
是的,但我可以(也想)通过GUI(我的应用程序)更改设置。 - Eric Jansen
1
简单来说,将变量okta_api_key设置为一个Promise,您可以多次等待它而不必重复执行异步任务。 - Kevin B
那么只需要说 const okta_api_key = doSomethingAsync(),然后在函数中说 const real_api_key = await okta_api_key()? - Eric Jansen
1个回答

11

你很接近:

 var okta_api_key = (async () => {
    return  await <getting key async>
 })();
创建一个promise,然后在需要使用它的时候 await 这个promise。

如何在文件(模块)顶层使用 await。

顶层 await 看起来很好:只需添加一个 await,就可以同步访问变量。但这样简化了问题:它将停止依赖于该模块的所有模块的执行。在大多数情况下,您不希望发生这种情况¹。相反,创建异步任务的promise,需要时再等待它。这样,您将异步执行限制在实际需要它的代码片段中。


¹极少数情况是:

1)加载一些全局配置,您必须在代码的任何地方访问它们,因此如果配置未准备好,则启动服务没有意义。

2)在您的服务的顶级文件中 await:由于没有模块依赖于它,因此这不会引起任何问题。


注意:顶级await尚未规定,并且NodeJS支持也不存在。要在生产中使用它,您必须等待几个月(?)。


这在 TL 上是不可能的吗? - Eric Jansen
变量okta_api_key = (async () => { return await process.env.OKTA_API_KEY; })();无法正常工作,因为在okta_api_key中存在Promise <akjhdkajbckjsygdfkjh(真实的API密钥)>。 - Eric Jansen
https://dev59.com/RGYq5IYBdhLWcg3wwDRA - Jonas Wilms
这是一篇有关JS异步函数的好文章,但它并不是我问题的答案。我想要一个被异步数据填充(因此不是立即可用)的var/const,可以被文件后面声明的2个函数访问。 - Eric Jansen
啊,我想你和 Kevin B(回复原帖的人)的意思是一样的,不是吗?那么我猜这就是正确的方法。 - Eric Jansen
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接