Как ждать асинхронную функцию в JavaScript на верхнем уровне? - PullRequest
0 голосов
/ 23 февраля 2019

Я знаю, что это ужасная идея.Но у меня есть 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 голосов
/ 23 февраля 2019

Просто используйте Обещание:

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 является победой.Но никогда не забывайте, что это просто сахар над Обещаниями.

0 голосов
/ 23 февраля 2019

Если вы хотите как можно меньше изменить существующий код, я бы подумал о том, чтобы изменить точку входа на модуль, который получает ключ, а затем вызвать модуль, который создает экземпляр 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
}

Короче говоря, все, что вам нужно сделать, это обернуть текущую точку входа в функцию.

0 голосов
/ 23 февраля 2019

верхний уровень - ужасная идея, да.Но я не понимаю, почему вы не можете просто поместить это в функцию?

const getAsync = async () => {
  const key = await get_async_data(config);
  return key;
}
getAsync().then(key => {
  const api = new API(key)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...