【问题标题】:How to wait for an async function in javascript at top level?如何在顶级的javascript中等待异步函数?
【发布时间】:2019-07-17 02:55:34
【问题描述】:

我知道这是一个糟糕的主意。但是我有一个 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

【问题讨论】:

  • 您能解释一下将代码包装在async 函数中(或仅使用.then)的问题吗?这似乎是显而易见的解决方案
  • 我想在我所有的课程中到处使用这个 API。我无法将所有内容都包装在一个巨大的异步函数中。
  • 不确定您的意思,但是您需要在需要等待承诺解决后再继续的任何地方等待此功能。或者,如果您不想将所有内容包装在异步函数中,只需使用 .then 即可。
  • 你能举一个更具体的例子吗? ATM并不是那么清晰
  • 只需调用 api,将生成的 promise 填充到 var 中,然后根据需要等待。

标签: javascript async-await


【解决方案1】:

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

const getAsync = async () => {
  const key = await get_async_data(config);
  return key;
}
getAsync().then(key => {
  const api = new API(key)
}

【讨论】:

  • 不需要await / async 如果你使用.then,只需get_async_data(config).then(key =>
  • 此外,这并不是一个“糟糕的想法”(这不是一个坏主意,目前有一个顶级await 的提议)作为目前规范不允许的想法。
  • 当然,但他似乎想要一个更小的函数可以在其他地方使用。也许涉及其他参数?无论是纯粹的 promise 还是写成 async await 都不存在。
  • 重新提议,我不知道,有趣。我仍然会说通常要避免在全局中执行任何功能,但我知道还有其他 POV。我想顶级 await 会让它感觉更像 PHP / Python-y。
  • 项目中的顶级并不一定意味着全局,幸运的是 - 这就是模块捆绑器的用途。
【解决方案2】:

只需使用 Promise:

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 是赢家。但永远不要忘记它只是 Promises 的糖。

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 2017-06-18
      • 2022-01-01
      • 1970-01-01
      • 2018-09-29
      • 2011-03-04
      • 2018-01-17
      • 2016-03-16
      • 2023-04-03
      相关资源
      最近更新 更多