在由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。