在导出中使用异步 js 导入 类

Using async js imports in exported classes

给定一个公开 async/dynamic 导出的包。我目前以这种方式导入(但我可以以不同的方式导入):

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

我打算重新公开 libEd 中的一些功能作为 class 的一部分:

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

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

我该怎么做?


更多信息:

我有几种方法可以解决这个问题:

  1. 如果 class 不需要立即实例化,那么我会等待库加载,然后将其传递给 class 构造函数。这是最干净的方式,因为库总是在 class.

  2. 中定义
  3. 如果 class 必须在获取库之前实例化,那么 class 中的方法必须处理未定义(例如尚未加载)的情况。然后你可以调用 await myClassInstance.init() 之类的东西来获取库。如果尚未加载库,我通常会为每个方法提供后备,可能是 returns 空字符串或虚拟 UI.

编辑:为选项 1 添加 TypeScript 示例

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();
}

我最终选择了三种方法之一:

  1. @Tim 的方法(已接受的答案):在 class 属性中包含导入,在构造函数时包含 await

    但是:在每个实例中存储导入可能会产生开销。


  1. await在 class 的每个方法中定义导入:
export class Something {
  static async from_X() {
    const libEd = await loadLibProm();
    return libEd.genFromX();
  }

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

但是:class API 现在都是异步的,使用起来更笨拙。


  1. 在代码开始时预加载导入。并希望在调用 class 时加载将完成。
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();
  }
}

但是:对于在导入完成之前/导入失败之后创建 class 实例的情况,这需要更好的错误处理。