背景
踩坑记录:LibGenerateTestUserSigFn is not a constructor
这一切都源于我个人的头铁行为。。。本来人家文档都说了要用cmd,vue-cli,我非要用vite,痛苦的折磨就开始了。
在开发过程中发现使用demo中提供的LibGenerateTestUserSigFn会报以下错误:
Uncaught TypeError: LibGenerateTestUserSigFn is not a constructor
最终在断点的帮助下,看到 new LibGenerateTestUserSigFn(options)的返回值如下图所是:
Symbol(Symbol.toStringTag): "Module"
Symbol.toStringTag是什么?
Symbol.toStringTag 是一个内置 symbol,它通常作为对象的属性键使用,对应的属性值应该为字符串类型,这个字符串用来表示该对象的自定义类型标签,通常只有内置的 Object.prototype.toString () 方法会去读取这个标签并把它包含在自己的返回值里。
通常使用Object.defineProperty(target, Symbol.toStringTag,{value:'Module'})定义Module对象
我再把包含LibGenerateTestUserSigFn类的文件拿去反序列化查看具体内容,发现在JS判断中把LibGenerateTestUserSigFn挂载到了window对象中却没有返回。
所以大胆猜测正是因为返回值undefined所以才导致无法顺利执行new操作,好在后面找到了大神的一篇文章,把LibGenerateTestUserSigFn包装了一下,将LibGenerateTestUserSigFn作为返回值返回。
/**
helper.ts
*/
/**
* 该方法用于处理 vite 编译 umd 包时, 在 es format 和 umd format 引入的格式不一致问题
* @param module - import * as PackageName 中的 PackageName 对象
* @param moduleName - UMD 包的 library 名称, 也就是导出到 Window 对象上的名称
*/
export const importHack = (module: any, moduleName: string) => {
if (typeof module === "function") {
return module;
}
if (module.default) {
return module.default;
}
const _window = window as any;
const wModule = _window[moduleName];
if (wModule) {
return wModule.default ? wModule.default : wModule;
}
if (module) {
return module;
}
throw new Error(`无法处理模块 : ${moduleName}`);
};
使用方法
import * as LibGenerateTestUserSigFn from './lib-generate-test-usersig.min.js';
import {importHack} from './helper'
//省略...
//省略...
const generator = new (importHack(LibGenerateTestUserSigFn, 'LibGenerateTestUserSig'))(SDKAppID, secretKey, EXPIRETIME);
const userSig = generator.genTestUserSig(userID);