如何在顶级JavaScript中等待异步功能?

时间:2019-02-22 23:58:49

标签: 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_async_data()(它确实返回一个Promise)。 除了将我所有的代码都放在一个巨大的异步函数中,我还可以调用await吗?

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

3 个答案:

答案 0 :(得分:0)

顶层是一个可怕的想法,是的。但是我不明白为什么不能只将它放在函数中?

override

答案 1 :(得分:0)

只需使用Promise:

0x10

同时,在另一个文件中...

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); 是赢家。但永远不要忘记,这只是对承诺的糖。

答案 2 :(得分:0)

如果您想尽可能少地更改现有代码,我会考虑将入口点更改为获取密钥的模块,然后调用实例化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
}

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