如何排查JSDOM的ResourceLoader问题及验证资源加载状态?
如何在JSDOM中判断外部资源是否加载成功
我正在用JSDOM加载以下HTML文件:
./template.html
<!doctype html> <html lang="en"> <head> <meta charset="utf-8" /> <title>title</title> </head> <body> <div>hi</div> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script> console.log(`2nd script: Does window.$ exist?`, window.$ !== undefined && window.$ !== null); console.log(`2nd script: Does $ exist?`, $ !== undefined && $ !== null); </script> </body> </html>
我的问题是,如何判断一个资源(例如https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js)是否成功加载?该URL仅为示例,我想了解通用的判断方法。
以下是我的项目结构:
项目结构
. ├── .eslintrc.json ├── .prettierrc ├── index.js ├── package.json └── template.html
./index.js
/* eslint-disable no-unused-vars */ import { JSDOM, ResourceLoader } from 'jsdom'; class CustomResourceLoader extends ResourceLoader { fetch(url, options) { console.log(`Called with ${url}`); return super.fetch(url, options); // was the resource loaded correctly? } } const dom = await JSDOM.fromFile(`./template.html`, { url: 'http://localhost', runScripts: 'dangerously', resources: new CustomResourceLoader(), pretendToBeVisual: true, }); const window = dom.window; const $1 = window.eval('window.$'); console.log( `jsdom module: Does window.$ exist?`, $1 !== undefined && $1 !== null );
./package.json
{ "name": "jsdom-sandbox", "version": "0.0.1", "description": "A simple sandbox for playing around with jsdom.", "main": "index.js", "type": "module", "scripts": { "test": "npm run exec && jasmine", "exec": "node index.js" }, "devDependencies": { "@types/jasmine": "^5.1.1", "@types/jquery": "^3.5.25", "@types/jsdom": "^21.1.4", "eslint": "^8.52.0", "eslint-config-prettier": "^9.0.0", "eslint-plugin-prettier": "^5.0.0", "jasmine": "^5.1.0" }, "dependencies": { "@prettier/sync": "^0.3.0", "jsdom": "^22.1.0", "prettier": "^3.0.3" } }
通用判断方法
1. 自定义ResourceLoader捕获加载状态
这是通用性最强的方法,能覆盖所有类型的资源(脚本、样式、图片等),且能获取详细错误信息。修改CustomResourceLoader的fetch方法,利用super.fetch返回的Promise判断状态:
class CustomResourceLoader extends ResourceLoader { async fetch(url, options) { console.log(`开始加载资源: ${url}`); try { const response = await super.fetch(url, options); // 通过HTTP状态码判断加载结果 if (response.status >= 200 && response.status < 300) { console.log(`资源加载成功: ${url}`); // 可在此记录成功状态,比如存入自定义变量 } else { console.log(`资源加载失败,状态码: ${response.status}, URL: ${url}`); } return response; } catch (error) { console.error(`资源加载出错: ${url}`, error); // 抛出错误让JSDOM继续处理,或自定义逻辑 throw error; } } }
- 网络错误、URL不可访问等情况会进入
catch块; - 服务器返回非2xx状态码(如404、500)时,可通过
response.status识别。
2. 检测资源暴露的全局变量
对于会在window上挂载全局变量的脚本(如jQuery的$),需等待页面load事件触发后再检测(资源加载是异步的):
// 等待页面所有资源加载完成 await new Promise(resolve => dom.window.addEventListener('load', resolve)); const isJqueryLoaded = !!dom.window.$; console.log(`jQuery是否加载成功?`, isJqueryLoaded);
也可以在页面内的后续脚本中直接判断,就像示例里的第二个<script>标签那样。这种方法适合依赖全局对象的脚本,但通用性稍弱。
3. 给资源标签添加加载事件
在HTML的资源标签(如<script>、<link>)上直接添加onload和onerror事件,监听单个资源的加载状态:
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js" onload="console.log('jQuery加载成功')" onerror="console.log('jQuery加载失败')"> </script>
这种方式简单直接,适合在页面内针对单个资源做状态判断。
内容的提问来源于stack exchange,提问作者Daniel Kaplan
相关产品推荐
相关产品推荐

