在由jsdom加载的脚本中设置全局variables
我试图在Node.js中运行一些浏览器代码,以简化testing( deasync是原因)。
目前,我使用jsdom来parsing唯一的html文件。 起初,我试图让它加载脚本,它们在<script>
标签中链接。 但由于相对文件path的一些愚蠢的问题,我已经切换到一个绝对path的列表传递给脚本文件作为参数jsdom.env
函数。
现在我很确定,jsdom正确地find我的脚本,但是我不能在其中设置任何全局variables。 此外, console.log
不在那里工作。 我已经检查过,如果通过require
命令加载脚本,那么全局variables和控制台输出都按预期工作。 但与jsdom.env
他们不工作。
我在Windows 7上使用Node.js 4.2.6版本。以下4个文件用于重现问题(它们位于同一个目录中):
main.js – 以node.exe开头:
var jsdom = require("jsdom"); require("./module"); var window = jsdom.env( '<p><a class="the-link" href="https://github.com/tmpvar/jsdom">jsdom!</a></p>', [ // "http://code.jquery.com/jquery.js", "file://" + __dirname + "/myjquery.js", "file://" + __dirname + "/script.js" ], undefined, function(error, window) { console.log("contents of a.the-link:", window.$("a.the-link").text()); console.log(global.hello, window.hello, global.hi); } );
module.js:
console.log("Hi!"); global.hi = 15
的script.js:
console.log("Hello!"); global.hello = 126;
myjquery.js只是从http://code.jquery.com/jquery.js下载的jQuery。
它打印出来:
Hi! contents of a.the-link: jsdom! undefined undefined 15
所以它肯定会加载myjquery.js
,因为它被用来打印第一行。 此外,它设置一个全局variables,并在模块中打印一行,但不会在脚本中执行。
你能解释一下为什么,并提出解决的办法吗?
hello
全球
global
是一个NodeJS的东西,而不是浏览器的东西。 在你的script.js
,如果你想在页面中设置全局variables(比如jQuery),你可以在全局范围声明它们:
var hello = 126;
或在window
上将它们分配为属性:
window.hello = 126;
或者(在全球范围内,如果你不使用严格模式):
this.hello = 126;
如果你在script.js
做了这些, window.hello
将被设置在你的callback中。
看到console.log
JSDom页面非常清楚地表明 ,要从窗口中看到console
输出,你必须做一些事情:
// Create and configure a virtual console var virtualConsole = jsdom.createVirtualConsole(); virtualConsole.on("log", function (message) { console.log("console.log called ->", message); }); // Use it in the config object var window = jsdom.env( '<p><a class="the-link" href="https://github.com/tmpvar/jsdom">jsdom!</a></p>', [ // "http://code.jquery.com/jquery.js", "file://" + __dirname + "/myjquery.js", "file://" + __dirname + "/script.js" ], { virtualConsole: virtualConsole }, // <== Here function(error, window) { console.log("contents of a.the-link:", window.$("a.the-link").text()); console.log(window.hello, global.hi); } );
看到错误
你提到你没有看到错误(这将是有用的,因为global.hello = 126;
确实会导致错误);
JSDom文档也讨论了如何监听错误:
virtualConsole.on("jsdomError", function (error) { console.error(error.stack, error.detail); });
这只是在我们的console
安装上面。 现在, script.js
等错误报告给Node控制台。
相对path
你提到了一些相对path的问题。 只是FYI,这对我来说工作得很好:
var window = jsdom.env( '<p><a class="the-link" href="https://github.com/tmpvar/jsdom">jsdom!</a></p>', [ "myjquery.js", "script.js" ], { virtualConsole: virtualConsole }, function(error, window) { console.log("contents of a.the-link:", window.$("a.the-link").text()); console.log(window.hello, global.hi); } );
…就像直接使用"http://code.jquery.com/jquery.js"
。
注意:关于virtualConsole的JSDom文档显示的configuration对象与我上面略有不同。 我做到了这一点:
var window = jsdom.env( // ... { virtualConsole: virtualConsole }, // ... );
而他们的文档显示了这一点:
var window = jsdom.env( // ... { virtualConsole }, // ... );
不同的原因是你只在你的代码中使用ES5,所以我翻译了。 他们正在使用ES2015(ES6)function,如果属性名称和您使用的variables名称相同,则可以使用简写forms指定属性。 所以{ virtualConsole }
和{ virtualConsole: virtualConsole }
在ES2015中是完全一样的,但前者在ES5和更早的版本中不起作用。 如果您正在使用当前的Node和JSDom,则可以使用该ES2015function。