关于chat-uikit-vue的LibGenerateTestUserSigFn踩坑记录

166 阅读2分钟

背景

踩坑记录:LibGenerateTestUserSigFn is not a constructor

这一切都源于我个人的头铁行为。。。本来人家文档都说了要用cmd,vue-cli,我非要用vite,痛苦的折磨就开始了。

头铁踩坑.png 在开发过程中发现使用demo中提供的LibGenerateTestUserSigFn会报以下错误:

Uncaught TypeError: LibGenerateTestUserSigFn is not a constructor

最终在断点的帮助下,看到 new LibGenerateTestUserSigFn(options)的返回值如下图所是:

Symbol(Symbol.toStringTag): "Module"

头铁2.png

Symbol.toStringTag是什么?

Symbol.toStringTag 是一个内置 symbol,它通常作为对象的属性键使用,对应的属性值应该为字符串类型,这个字符串用来表示该对象的自定义类型标签,通常只有内置的 Object.prototype.toString () 方法会去读取这个标签并把它包含在自己的返回值里。

通常使用Object.defineProperty(target, Symbol.toStringTag,{value:'Module'})定义Module对象

我再把包含LibGenerateTestUserSigFn类的文件拿去反序列化查看具体内容,发现在JS判断中把LibGenerateTestUserSigFn挂载到了window对象中却没有返回。

头铁3.png

所以大胆猜测正是因为返回值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);

参考文章

如何在 Vite 中使用 UMD 的包