如何在顶层等待javascript中的异步函数?

如何在顶层等待javascript中的异步函数?,javascript,async-await,Javascript,Async Await,我知道这是个糟糕的主意。但是我有一个API,在我有一段只能异步获取的数据之前,我不能使用它。大概是这样的: const key = await get_async_data(config) // NOT RIGHT, can't use await at top level const api = new API(key) ... use api ... 这是在顶层,在任何函数之外,所以我不能只等待get\u async\u data()(它确实返回一个承诺)。 除了把我所有的代码放在一个巨大

我知道这是个糟糕的主意。但是我有一个API,在我有一段只能异步获取的数据之前,我不能使用它。大概是这样的:

const key = await get_async_data(config) // NOT RIGHT, can't use await at top level
const api = new API(key)
... use api ...
这是在顶层,在任何函数之外,所以我不能只等待get\u async\u data()(它确实返回一个承诺)。 除了把我所有的代码放在一个巨大的异步函数中以便调用wait,还有什么不足吗

API
只是一个由模块导出的类(由我控制)

(顺便说一句,我想把代码放到
API
类的构造函数中,但是构造函数当然也不能是异步的。)

如果未设置,我可以让
API
的每个异步方法都设置密钥,但这非常具有侵入性,而且容易出错

因此,我不是在问如何让顶层代码等待,而是在寻找其他方法来构造它,以便异步调用干净地进行

这里有一些更详细的情况,以防这有所帮助。 在api.js中:

class API {
  constructor(key) {
    this.key = key
    // other stuff
  }
  async f1(a) {
  }
  async f2(b, c) {
  }
  f3() {
    return true
  }
}
export default API
然后在将使用它的地方(许多):

import API from '@/api'

const key = async get_key() // NOPE
const theAPI = new API(key)

async importantMethod(args)
{
  return await theAPI.f1(args)
}
async otherMethod()
{
  if (theAPI.f3)
    return await theAPI.f2(123)
  // etc...
}
// ... and so on

顶层是个糟糕的主意,是的。但我不明白为什么你不能把它放在函数里

const getAsync = async () => {
  const key = await get_async_data(config);
  return key;
}
getAsync().then(key => {
  const api = new API(key)
}
只要用承诺:

const pendingAPI = get_async_data(config).then(key => new API(key)); // N.B. no await
export default pendingAPI;
同时,在另一个文件中

import pendingAPI from 'other/file';
pendingAPI.then(doStuffWithAPI);

有时
async/await
是一种胜利。但是别忘了,这只是对承诺的糖。

如果你想尽可能少地改变你现有的代码,我会考虑将入口点更改为获取密钥的模块,然后调用实例化API(旧的入口点)的模块。例如:

// start.js
import makeApi from './makeApi';
get_key()
  .then(makeApi);

// makeApi.js
export default function(key) {
  const theApi = new API(key);
  function importantMethod(args) {
    return theAPI.f1(args)
  }
  function otherMethod() {
    if (theAPI.f3)
      return theAPI.f2(123)
  }
  // etc
}

简而言之,您所要做的就是将当前入口点包装到函数中。

您能解释一下将代码包装到
异步
函数中(或仅使用
。然后
)时遇到的问题吗?这似乎是一个显而易见的解决方案,我想在我所有的类中的任何地方都使用这个API。我不能把所有的东西都封装在一个巨大的异步函数中。我不确定你的意思,但是你需要在任何地方等待这个函数,你需要等待承诺的解决,然后才能继续。或者,如果你不想把所有的东西都用异步函数来包装,那就用use吧。那么你能用更多的代码给出一个更具体的例子吗,这样我们就可以看到什么东西看起来太乱了?还不太清楚的是,ATM必须调用api,将产生的承诺填充到var中,然后根据需要等待。如果使用
,则不需要
等待
/
异步
。然后
,只需执行
获取异步数据(配置)。然后(key=>
同样,这也不是一个“糟糕的想法”(这不是一个坏主意,目前有一个顶级
wait
的提案)这是一个目前规范不允许的想法。当然,但他似乎想在其他地方使用一个更小的函数。可能涉及其他参数?而且无论它是纯承诺还是写为async await都不在这里或那里。如果是建议,我不知道,很有趣。我仍然会说在gl中做任何功能obal通常是要避免的,但我知道在这方面还有其他POV。我想顶级await会让它感觉更像PHP/Python-y。幸运的是,项目中的顶级并不一定意味着全局性——这就是模块捆绑包的用途。