防止导入ES模块的CommonJS模块执行代码

Prevent CommonJS module imported into ES module from executing code

我正在尝试将 CommonJS 模块 (KeyboardJS) 导入到我在 ES 模块中编写的一些测试中。

这是我的测试代码,给你一个想法:

import { JSDOM } from 'jsdom'
import assert from 'assert'
import keyboardjs from 'keyboardjs' // <-- this line throws an error

// create mocked window object
const window = new JSDOM().window
const document = window.document

// pass this to keyboardjs?
keyboardjs.watch(document)

这里是错误:

Error: Cannot find window functions addEventListener or attachEvent.
    at Keyboard.watch (./node_modules/keyboardjs/dist/keyboard.js:614:19)
    at Keyboard.setContext (./node_modules/keyboardjs/dist/keyboard.js:587:14)
    at new Keyboard (./node_modules/keyboardjs/dist/keyboard.js:439:12)
    at ./node_modules/keyboardjs/dist/keyboard.js:1076:18
    at ./node_modules/keyboardjs/dist/keyboard.js:2:83
    at Object.<anonymous> (./node_modules/keyboardjs/dist/keyboard.js:5:2)
    at Module._compile (internal/modules/cjs/loader.js:1063:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
    at Module.load (internal/modules/cjs/loader.js:928:32)
    at Function.Module._load (internal/modules/cjs/loader.js:769:14)
    at ModuleWrap.<anonymous> (internal/modules/esm/translators.js:199:29)
    at ModuleJob.run (internal/modules/esm/module_job.js:152:23)
    at async Loader.import (internal/modules/esm/loader.js:166:24)
    at async formattedImport (./node_modules/mocha/lib/nodejs/esm-utils.js:7:14)
    at async Object.exports.requireOrImport (./node_modules/mocha/lib/nodejs/esm-utils.js:48:32)
    at async Object.exports.loadFilesAsync (./node_modules/mocha/lib/nodejs/esm-utils.js:88:20)
    at async singleRun (./node_modules/mocha/lib/cli/run-helpers.js:125:3)
    at async Object.exports.handler (./node_modules/mocha/lib/cli/run.js:374:5)

似乎 keyboardjs 正在尝试访问 window 对象 ,而它正在加载 ,这当然不能工作,因为我正在加载它在一些测试代码中。

是否有一些特殊的方法可以在不触发此行为的情况下导入它?

我能够使用 dynamic imports.

让它工作

您可以使用 import 函数,该函数 returns 用于导入模块时的 Promise。

JSDOM 可以先导入,然后用于创建一个嵌入的 window 对象,然后我们将其添加到全局范围。

然后,我们可以使用相同的机制导入 keyboardjs

这是我最终得到的大致代码:

// import JSDOM first
import('jsdom').then(async module => {
  const window = new module.JSDOM().window

  // now set the global window object to the JSDOM window
  globalThis.window = window

  // _now_ import keyboardjs
  const keyboardjs = await import('keyboardjs')
  const document = window.document
  return { keyboardjs, document }
}).then(({ keyboardjs, document }) => {
  // test code goes here, and can use keyboardjs and document
})