【问题标题】:In PhantomJS, why does jQuery call cause script to hang?在 PhantomJS 中,为什么 jQuery 调用会导致脚本挂起?
【发布时间】:2015-09-14 22:41:21
【问题描述】:

我在 Mac OS X Yosemite 上使用 PhantomJS 2.0.0:

$ phantomjs --version
2.0.0

如下所示,我的脚本似乎挂在调用$('h1').size() 的行:

system = require('system');

function usage() {
  console.log("usage: phantomjs " + system.args[0] + " <url>");
  phantom.exit(1);
}

console.log("system.args.length=" + system.args.length);
if (system.args.length != 2) {
  console.log("usage bad....");
  usage();
} else {
  var url = system.args[1];
  var page = require('webpage').create();

  console.log("Opening page: " + url);
  page.open(url, function (status) {
      if (status !== "success") {
        console.log("Unable to access network");
      } else {
        console.log("Setting timeout...");
        window.setTimeout(function() {
          page.includeJs("http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js", function() {
            console.log("Searching for Seawolf Calendar...");
            console.log("h1.size=" + $('h1').size());

            console.log("Exiting with status 0...");
            phantom.exit(0);
          });
        }, 5000);
      }
  });
}

脚本是这样从命令行调用的,例如:

phantomjs download-framed-content.js "http://www.sonoma.edu/calendar/groups/clubs.html"

输出如下:

system.args.length=2 打开页面:http://www.sonoma.edu/calendar/groups/clubs.html 设置超时... 正在搜索海狼日历... [挂...]

为什么 jQuery 调用会挂起脚本?

【问题讨论】:

  • 我注意到你从不赞成你得到的答案。我不知道这是为什么。我的回答是否缺少一些信息或其他方面不好?

标签: javascript jquery phantomjs


【解决方案1】:

PhantomJS 2.0.0 由于某种原因没有显示任何错误(这是一个已知错误)。

错误是$ 不是函数。如果页面中存在 jQuery,那么您可以在页面中使用它,但它不能在页面上下文之外(在 page.evaluate() 内)工作。

你只能通过page.evaluate()访问DOM/页面上下文:

console.log("h1.size=" + page.evaluate(function(){
    return $('h1').size();
}));

请注意,您不能在 page.evaluate() 内使用任何外部变量,因为它是沙盒的。 documentation 说:

注意:evaluate 函数的参数和返回值必须是简单的原始对象。经验法则:如果可以通过 JSON 序列化就可以了。

闭包、函数、DOM 节点等将起作用!

【讨论】:

  • 我只是在从 page.evaluate() 返回数组时遇到了麻烦。也许这也是一个错误?
  • 考虑到我回答的最后一部分,这可能是预期的行为。如果它是[1, 2, 3] 中的实际数组,那么不,这应该不是问题。请记住,$(selector) 是一个仅模仿 JavaScript 数组行为的 jQuery 集合。它(及其内容)不能被​​序列化以将其传递到外部。