【问题标题】:In Casper JS (based on Phantom JS), how to catch JavaScript errors that are loaded after the DOM is done?在 Casper JS(基于 Phantom JS)中,如何捕获 DOM 完成后加载的 JavaScript 错误?
【发布时间】:2016-07-20 21:15:34
【问题描述】:

我有一个Casper JS 脚本(Casper JS 基于Phantom JS),它将另一个脚本注入到外部 URL 中。注入的脚本在加载 DOM 后运行代码,类似于 jQuery 的 $(document).ready() 的工作方式。

如果注入的脚本包含 JavaScript 错误,那么如果在 DOM 之后加载,Casper JS 将不会捕获它。如果立即运行,Casper 将捕获错误。

下面的代码不会输出错误ReferenceError: Strict mode forbids implicit creation of global property 'string'。如果您查看最底线,则可以交换行中的 cmets 以获取此错误。我希望即使在加载 DOM 后运行代码时也会发生此错误。

要运行代码,安装 Casper JS 并在控制台中输入:casperjs casper.js

casper.js

// Include Casper's "utils" so we can dump variables.
var require = patchRequire(require);
var utils = require('utils');

// Open a URL and inject our JS.
var casper = require('casper').create();
casper.start('http://example.com/', function() {
  casper.page.injectJs('inject.js');
});

// Wait a moment to give everything time to load, then check that the function
// exists and returns something.
casper.wait(1000, function() {
  var testValue = casper.evaluate(function() {
    return test();
  });

  casper.echo(testValue);
});

// If there are any errors along the way, then print them.
casper.on('page.error', function(msg, trace) {
  casper.echo(msg);
  casper.echo(utils.dump(trace));
});

// Actually run everything.
casper.run();

inject.js

// Be strict on this page so that errors occur.
'use strict';

function run() {
  window.test = function() {
    // An error will occur here because the variable was never declared.
    testing = 'test';
    return testing;
  }
}

// If the below line is used, then "ReferenceError: Strict mode forbids implicit
// creation of global property 'string'" appears as expected.
// run();

// If the below line is used instead of the one above, then the same error does
// not appear.
document.addEventListener('DOMContentLoaded', run);

【问题讨论】:

  • casper.on('page.error') 应该在页面上显示任何错误,它不起作用吗?
  • 不,正如我所说,如果 run() 函数是通过 DOMContentLoaded 事件侦听器运行而不是裸运行,它不会显示 ReferenceError。

标签: javascript dom phantomjs casperjs code-injection


【解决方案1】:

看来您注入脚本inject.js 为时已晚,在页面加载并触发事件之后。

有一种方法可以在页面初始化之后、加载之前进行注入:

casper.on('page.initialized', function(msg, trace) {
  casper.echo("Injecting JS");
  casper.page.injectJs('inject.js');
});


还有一个注意事项。你写道:

如果 run() 函数通过 DOMContentLoaded 事件运行,则不会显示 ReferenceError

正如我们现在所知,它实际上从未通过 DOMContentLoaded 事件运行。我相信你会这样做,但我觉得再次强调我们应该记录所有内容非常重要,尽可能在任何地方记录以防万一。

所以我总是添加到像 casper.js 这样的脚本中,不仅是 page.error,而且还有 remote.message 回调,以便能够从 casper.page 上下文中 console.log()

casper.on('remote.message', function(msg) {
  casper.echo(msg);
});

然后在inject.js 中添加一个console.log 调用:

function run() {
  window.test = function() {

    console.log("run() has run");

    // An error will occur here because the variable was never declared.
    testing = 'test';
    return testing;
  }
}

并发现它没有运行(不是因为严格模式它不只是产生错误)。

【讨论】:

  • DOMContentLoaded 中的代码根本不运行的任何原因?我在这个例子中使用了这个事件,因为在我的实际代码中,我已经通过 WebPack 将 jQuery 导入到注入的代码中,这对于一个例子来说太重了,所以我试图简化它。我使用 jQuery 的 $(document).ready()。代码肯定会在这种情况下运行,因为我在 Casper 中运行的测试可以检测到注入代码所做的更改,这些代码在 DOM 加载完成后运行。
  • 好的,所以我用 jQuery 的 $() 进行了测试,并且成功了,所以他们当然做了一些额外的东西,而不仅仅是简单的 DOMContentLoaded。您使用 remote.message 以便我可以使用 console.log 进行调试的提示非常有帮助。我设法从那里弄清楚了。最终,page.error 确实是我需要用来输出我想要的错误的事件。
  • 我认为 DOMContentLoaded 没有运行,因为您在 page.open 回调中注入了 inject.js,而上述事件已经触发。
猜你喜欢
  • 1970-01-01
  • 2017-09-24
  • 2014-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-27
  • 2013-04-02
  • 1970-01-01
相关资源
最近更新 更多