Использование asyn c js импорта в экспортируемых классах - PullRequest
0 голосов
/ 03 марта 2020

Имеется пакет, который предоставляет асинхронный / динамический экспорт c. Который я сейчас импортирую таким образом (но я мог бы импортировать его по-другому):

(async function() {
  const libEd = await import("../../.cache/ed25519wars/index.js");
})();

Я намереваюсь повторно представить некоторые функции из libEd как часть класса:

export class Something {
  static from_X() {
    return libEd.genFromX();
  }

  do_Y() {
    return libEd.doY();
  }
}

Как я могу это сделать?


Для получения дополнительной информации:

  • Пакет, который предоставляет асинхронный / динамический c экспорт, генерируется веб-пакетом упаковка веб-сборки. Я не уверен, что смогу что-либо изменить в этой части
  • Я бы определенно мог изменить способ импорта этого пакета
  • Я также мог бы изменить способ повторного экспонирования / группировки функций ( и использовать что-то еще, кроме класса)

Ответы [ 2 ]

1 голос
/ 03 марта 2020

Есть несколько способов, которыми я бы подошел к этому:

  1. Если класс не нуждается в немедленном создании экземпляра, тогда я буду ждать загрузки библиотеки, а затем передать ее конструктор класса. Это самый чистый способ, поскольку библиотека всегда определяется внутри класса.

  2. Если класс должен быть создан перед извлечением библиотеки, то методы в классе должны обрабатывать ситуацию, когда она не определено (например, еще не загружено). Затем вы можете вызвать что-то вроде await myClassInstance.init(), чтобы получить библиотеку. Обычно я предоставляю запасной вариант для каждого метода, если библиотека еще не загружена, возможно, она возвращает пустую строку или фиктивный пользовательский интерфейс.

РЕДАКТИРОВАТЬ: добавление примера TypeScript для опции 1

interface MyLibrary {
  libraryMethod: () => void;
}

class ExampleClass {
  localLib: MyLibrary;

  constructor(lib: MyLibrary) {
    this.localLib = lib;
  }

  myClassMethod() {
    this.localLib.libraryMethod();
  }
}

async function run() {
  // first we fetch the remote library
  const myLibrary: MyLibrary | undefined = await import('/lib.js');

  // good practise to add some check here
  if (!myLibrary) {
    throw Error('failed to fetch myLib');
  }

  // then we create the class instance using the downloaded library
  const myClassInstance = new ExampleClass(myLibrary);

  // now we can call our class method which definitely has the remote library
  myClassInstance.myClassMethod();
}
0 голосов
/ 03 марта 2020

Я остановился на одном из трех методов:

  1. @ Метод Тима (принятый ответ): включите импорт в свойствах класса и await во время конструктора.

    Но: при сохранении импорта в каждом экземпляре могут быть накладные расходы.


await в каждом методе класса для определения импорта, определенного там:
export class Something {
  static async from_X() {
    const libEd = await loadLibProm();
    return libEd.genFromX();
  }

  async do_Y() {
    const libEd = await loadLibProm();
    return libEd.doY();
  }
}

Но: API класса теперь все асин c и более неудобно в использовании.


Предварительная загрузка импорта при запуске кода. И надеемся, что загрузка будет завершена при вызове класса.
let libEd: typeof import("../../.cache/ed25519wars/index.js");
async function loadLibProm(): Promise<
  typeof import("../../.cache/ed25519wars/index.js")
> {
  libEd = await import("../../.cache/ed25519wars/index.js");
  return libEd;
}
loadLibProm(); // this somehow starts running the promise ?? wut ? Anyways that's what we want

export class Something {
  static from_X() {
    return libEd.genFromX();
  }

  do_Y() {
    return libEd.doY();
  }
}

Но: это требует лучшей обработки ошибок для случая, когда экземпляр класса создан до завершения импорта / после сбоя импорта.

...