gpt4 book ai didi

node.js - 运行时加载 Typescript 动态模块

转载 作者:搜寻专家 更新时间:2023-10-30 21:48:24 25 4
gpt4 key购买 nike

我在 NodeJS Typescript 项目中定义了一个抽象的 BaseClass,并且我有一个派生类的列表,这些派生类实现和扩展了这个 BaseClass

// baseModule.ts
export abstract class BaseClass {
constructor() {}
abstract method(): void;
}

export interface ModuleConstructor<T extends BaseClass> {
new (): T
}

export function createModule<T extends BaseClass>(type: ModuleConstructor<T>): T {
return new type();
}

我正在尝试找到一种在运行时以编程方式创建这些类之一的实例的方法。

这里的约束是我希望能够将新的 myDerivedClass.ts 文件放入我的项目文件夹中,并让它在运行时自动包含在可用模块列表中。

开发人员的工作流程是 1) 创建新文件 myNewModule.ts 2) 创建并导出一个扩展 BaseClass 的类 3) 保存 myNewModule.ts./myModules

// ./myModules/myNewModule.ts
export class MyModule extends BaseClass {
constructor() {
super()
}

method() {
//Do something custom
}
}

运行时流程(理想情况下无需重建)将是 1) 用户从可用模块列表中选择 2) createModule 工厂函数创建所选模块的新实例并作为

// someOtherClass.ts

const modules = require('./myModules/*') //<- Something to this effect
import { BaseClass, createModule, ModuleConstructor } from './BaseClass'

export class SomeOtherClass {
public mod: BaseClass
constructor(mod: ModuleConstructor) {
this.mod = createModule(mod)
}
}

for (let m in modules) {
console.log(modules[m].name);
}

let someObj = SomeOtherClass(modules[m]);
someObj.mod // <- instance of derived class.

最佳答案

这是我最终使用的解决方案,不过也许还有更简单的方法。

1) 创建动态模块加载函数2) 使用NodeJS fs 模块扫描包含模块的目录3) 遍历每个文件并将文件动态导入到数组中

// BaseModule.ts
import * as path from 'path'
import { promisify } from 'utils'

const readdirAsync = promisify(fs.readdir);

export async function loadModules() {
let files = await readdirAsync(path.resolve(__dirname, 'rel/path/to/modules'));
let imports = await Promise.all(files.map(file => (
import(path.resolve(__dirname, '..', './exchanges/brokers', file))))
)

// this next part will depend on how you're exporting within
// the module. In my case, each module has an "export class"
// statement. Typically you would "import { className } from 'moduleName'"

let moduleNames: { [name: string]: number } = {};
let modules: ModuleConstructor<BaseClass>[] = [];
for (let i in imports) {
Object.keys(imports[i]).forEach((key: string) => {
moduleNames[key] = modules.length;
modules.push(imports[i][key])
})
}
return [moduleNames, modules];
}


// someOtherClass.ts
import { BaseClass, loadModules, ModuleConstructor } from './BaseClass'

export class SomeOtherClass<T extends BaseClass> {
public mod: T
constructor(mod: T ) {
this.mod = mod;
}
}

loadModules()
.then(([moduleNames, modules]: [string[], ModuleConstructor<BaseClass>[]] => {

// not necessary, but just for purpose of demonstration
let names: string[] = Object.keys(moduleNames);
let name = names[0]; // pick one of the module names

// use the name dictionary as a lookup into the constructor array
let someObj = SomeOtherClass(new modules[moduleNames[name]]);
someObj.mod // <- instance of derived class.
})
.catch((err) => {
console.log(err.message);
});

这样做之后我意识到 NPM 包 systemJS 处理动态加载器。

关于node.js - 运行时加载 Typescript 动态模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50533921/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com