在jsdom加载的脚本中设置全局变量
Setting global variables in a script loaded by jsdom
我正在尝试 运行 Node.js 中的一些浏览器代码以简化测试(deasync 是原因)。
目前,我使用jsdom解析唯一的html文件。起初,我试图让它也加载脚本,这些脚本链接在 <script>
标签中。但是由于相对文件路径的一些愚蠢问题,我已经切换到将脚本文件的绝对路径列表作为参数传递给 jsdom.env
函数。
现在我很确定 jsdom 能正确找到我的脚本,但我不能在其中设置任何全局变量。此外,console.log
不在那里工作。我检查过如果我通过 require
命令加载脚本,那么全局变量和控制台输出都按预期工作。但是 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 只是 jQuery 从 http://code.jquery.com/jquery.js 下载的。
打印出来:
Hi!
contents of a.the-link: jsdom!
undefined undefined 15
所以它肯定会正确加载 myjquery.js
,因为它用于打印第一行。此外,它设置了一个全局变量并在模块中打印了一行,但它并没有在脚本中执行。
能否解释一下原因并提出解决方法?
hello
全局
global
是 NodeJS 的东西,不是浏览器的东西。在你的 script.js
中,如果你想在页面中设置全局变量(就像 jQuery 那样),你要么只在全局范围内声明它们:
var hello = 126;
或将它们指定为 window
上的属性:
window.hello = 126;
或(在全局范围内并且如果您未使用严格模式)到 this
:
this.hello = 126;
如果您执行 script.js
中的任何操作,window.hello
将在您的回调中设置。
看到console.log
要从 window 中查看 console
输出的 JSDom 页面 quite clearly says,您必须做一些事情:
// 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 documentation 也谈到了如何侦听错误:
virtualConsole.on("jsdomError", function (error) {
console.error(error.stack, error.detail);
});
那只是在我们上面的 console
设置之后。现在,script.js
等错误会报告给节点控制台。
相对路径
您提到了相对路径的一些问题。仅供参考,这对我来说效果很好:
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 文档显示的配置对象与我上面做的略有不同。我这样做了:
var window = jsdom.env(
// ...
{ virtualConsole: virtualConsole },
// ...
);
而他们的文档显示:
var window = jsdom.env(
// ...
{ virtualConsole },
// ...
);
不同的原因是你只在你的代码中使用了 ES5,所以我翻译了。他们正在使用 ES2015 (ES6) 功能,如果 属性 名称和您从中获取它的变量名称相同,则允许您使用 shorthand 指定 属性 .所以 { virtualConsole }
和 { virtualConsole: virtualConsole }
在 ES2015 中是完全一样的东西,但前者在 ES5 及更早版本中不起作用。如果您使用当前的 Node 和 JSDom,则可以使用该 ES2015 功能。
我正在尝试 运行 Node.js 中的一些浏览器代码以简化测试(deasync 是原因)。
目前,我使用jsdom解析唯一的html文件。起初,我试图让它也加载脚本,这些脚本链接在 <script>
标签中。但是由于相对文件路径的一些愚蠢问题,我已经切换到将脚本文件的绝对路径列表作为参数传递给 jsdom.env
函数。
现在我很确定 jsdom 能正确找到我的脚本,但我不能在其中设置任何全局变量。此外,console.log
不在那里工作。我检查过如果我通过 require
命令加载脚本,那么全局变量和控制台输出都按预期工作。但是 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 只是 jQuery 从 http://code.jquery.com/jquery.js 下载的。
打印出来:
Hi!
contents of a.the-link: jsdom!
undefined undefined 15
所以它肯定会正确加载 myjquery.js
,因为它用于打印第一行。此外,它设置了一个全局变量并在模块中打印了一行,但它并没有在脚本中执行。
能否解释一下原因并提出解决方法?
hello
全局
global
是 NodeJS 的东西,不是浏览器的东西。在你的 script.js
中,如果你想在页面中设置全局变量(就像 jQuery 那样),你要么只在全局范围内声明它们:
var hello = 126;
或将它们指定为 window
上的属性:
window.hello = 126;
或(在全局范围内并且如果您未使用严格模式)到 this
:
this.hello = 126;
如果您执行 script.js
中的任何操作,window.hello
将在您的回调中设置。
看到console.log
要从 window 中查看 console
输出的 JSDom 页面 quite clearly says,您必须做一些事情:
// 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 documentation 也谈到了如何侦听错误:
virtualConsole.on("jsdomError", function (error) {
console.error(error.stack, error.detail);
});
那只是在我们上面的 console
设置之后。现在,script.js
等错误会报告给节点控制台。
相对路径
您提到了相对路径的一些问题。仅供参考,这对我来说效果很好:
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 文档显示的配置对象与我上面做的略有不同。我这样做了:
var window = jsdom.env(
// ...
{ virtualConsole: virtualConsole },
// ...
);
而他们的文档显示:
var window = jsdom.env(
// ...
{ virtualConsole },
// ...
);
不同的原因是你只在你的代码中使用了 ES5,所以我翻译了。他们正在使用 ES2015 (ES6) 功能,如果 属性 名称和您从中获取它的变量名称相同,则允许您使用 shorthand 指定 属性 .所以 { virtualConsole }
和 { virtualConsole: virtualConsole }
在 ES2015 中是完全一样的东西,但前者在 ES5 及更早版本中不起作用。如果您使用当前的 Node 和 JSDom,则可以使用该 ES2015 功能。