在导出中使用异步 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();
}
}
我该怎么做?
更多信息:
- 暴露async/dynamic exports的包是webpack打包webassembly生成的。我不确定我是否可以更改这部分的任何内容
- 我绝对可以改变导入该包的方式
- 我还可以更改重新公开/分组功能的方式(并使用 class 以外的其他方式)
我有几种方法可以解决这个问题:
如果 class 不需要立即实例化,那么我会等待库加载,然后将其传递给 class 构造函数。这是最干净的方式,因为库总是在 class.
中定义
如果 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();
}
我最终选择了三种方法之一:
@Tim 的方法(已接受的答案):在 class 属性中包含导入,在构造函数时包含 await
。
但是:在每个实例中存储导入可能会产生开销。
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 现在都是异步的,使用起来更笨拙。
- 在代码开始时预加载导入。并希望在调用 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 实例的情况,这需要更好的错误处理。
给定一个公开 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();
}
}
我该怎么做?
更多信息:
- 暴露async/dynamic exports的包是webpack打包webassembly生成的。我不确定我是否可以更改这部分的任何内容
- 我绝对可以改变导入该包的方式
- 我还可以更改重新公开/分组功能的方式(并使用 class 以外的其他方式)
我有几种方法可以解决这个问题:
如果 class 不需要立即实例化,那么我会等待库加载,然后将其传递给 class 构造函数。这是最干净的方式,因为库总是在 class.
中定义
如果 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();
}
我最终选择了三种方法之一:
@Tim 的方法(已接受的答案):在 class 属性中包含导入,在构造函数时包含
await
。但是:在每个实例中存储导入可能会产生开销。
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 现在都是异步的,使用起来更笨拙。
- 在代码开始时预加载导入。并希望在调用 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 实例的情况,这需要更好的错误处理。