在jsdom加载的脚本中设置全局变量 [英] Setting global variables in a script loaded by jsdom

查看:108
本文介绍了在jsdom加载的脚本中设置全局变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在Node.js中运行一些浏览器代码,以简化测试(取消同步是原因).

I'm trying to run some browser code in Node.js in order to simplify testing (deasync is the reason).

当前,我使用 jsdom 来解析唯一的html文件.最初,我试图使其也加载脚本,这些脚本链接在< script> 标记中.但是由于相对文件路径存在一些愚蠢的问题,我转而使用传递到脚本文件的绝对路径列表作为 jsdom.env 函数的参数.

Currently, I use jsdom to parse the only html file. At first, I was trying to make it also load the scripts, which are linked in <script> tags. But due to some stupid issues with relative file paths I have switched to passing a list of absolute paths to the script files as a parameter to jsdom.env function.

现在,我非常确定jsdom可以正确找到我的脚本,但是我无法在其中设置任何全局变量.另外, console.log 在那里不起作用.我已经检查了是否通过 require 命令加载脚本,那么全局变量和控制台输出均按预期工作.但是,使用 jsdom.env 时,它们不起作用.

Now I'm pretty sure that jsdom finds my scripts properly, but I cannot set any global variables in them. Also, console.log is not working there. I have checked that if I load a script through require command, then both global variables and console output are working as expected. But with jsdom.env they are not working.

我在Windows 7上使用Node.js版本4.2.6.以下4个文件用于重现此问题(它们位于同一目录中):

I use Node.js version 4.2.6 on Windows 7. The following 4 files are used to reproduce the issue (they are located in the same directory):

main.js-以node.exe开头:

main.js - started with 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:

module.js:

console.log("Hi!");
global.hi = 15

script.js:

script.js:

console.log("Hello!");
global.hello = 126;

myjquery.js只是从 http://code.jquery.com/jquery.js .

myjquery.js is just jQuery downloaded from http://code.jquery.com/jquery.js.

它打印出来:

Hi!
contents of a.the-link: jsdom!
undefined undefined 15

因此它肯定会正确加载 myjquery.js ,因为它用于打印第一行.另外,它设置了一个全局变量并在模块中打印了一行,但是在脚本中却没有这样做.

So it definitely loads myjquery.js properly, because it is used to print the first line. Also, it sets a global variable and prints a line in the module, but it does not do it in the script.

能否请您解释原因并提出解决方法?

Could you please explain why and propose a way to fix it?

推荐答案

全局 hello

global 是NodeJS,而不是浏览器.在您的 script.js 中,如果要在页面中设置全局变量(如jQuery一样),则只需在全局范围内声明它们即可:

The hello global

global is a NodeJS thing, not a browser thing. In your script.js, if you want to set global variables in the page (like jQuery does), you would either just declare them at global scope:

var hello = 126;

或将它们分配为 window 上的属性:

or assign them as properties on window:

window.hello = 126;

或(在全局范围内,如果您未使用严格模式):

or (at global scope and if you're not using strict mode) to this:

this.hello = 126;

如果您在 script.js 中执行任何操作,则会在回调中设置 window.hello .

If you do any of those in script.js, window.hello will be set in your callback.

JSm页面很多人明确表示说要看到 console 从窗口中输出,您必须执行以下操作:

The JSDom page quite clearly says that to see console output from within the window, you must do something:

// 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; 确实会导致错误);

JSm文档讨论了如何收听也有错误:

The JSDom documentation talks about how to listen for errors, too:

virtualConsole.on("jsdomError", function (error) {
  console.error(error.stack, error.detail);
});

那只是在我们上面的 console 设置之后.现在, script.js 中的错误等将报告给Node控制台.

That just goes after our console setup above. Now, errors in script.js and such are reported to the Node console.

您已经提到相对路径的一些麻烦.仅供参考,这对我来说很好:

You'd mentioned some trouble with relative paths. Just FYI, this worked just fine for me:

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" 一样.

...as did using "http://code.jquery.com/jquery.js" directly.

旁注: virtualConsole 周围的JSm文档显示的配置对象与我上面做的稍有不同.我是这样做的:

Side note: The JSDom documentation around virtualConsole shows the configuration object slightly different than I do above. I did this:

var window = jsdom.env(
  // ...
  { virtualConsole: virtualConsole },
  // ...
);

而他们的文档显示了这一点:

whereas their docs show this:

var window = jsdom.env(
  // ...
  { virtualConsole },
  // ...
);

差异的原因是您仅在代码中使用了ES5,所以我翻译了.他们正在使用ES2015(ES6)功能,如果属性名称和您要使用的变量名称相同,则可以使用简写形式指定属性.因此, {virtualConsole} {virtualConsole:virtualConsole} 在ES2015中完全相同,但是前者在ES5及更早版本中不起作用.如果您正在使用当前的Node和JSm,则可以使用该ES2015功能.

The reason for the difference is that you were using ES5 only in your code, so I translated. They're using an ES2015 (ES6) feature that lets you specify a property using a shorthand if the property name and the name of the variable you're taking it from are the same. So { virtualConsole } and { virtualConsole: virtualConsole } are exactly the same thing in ES2015, but the former doesn't work in ES5 and earlier. If you're using the current Node and JSDom, you can use that ES2015 feature.

这篇关于在jsdom加载的脚本中设置全局变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆