在 Casper JS(基于 Phantom JS)中,如何捕获 DOM 完成后加载的 JavaScript 错误?

In Casper JS (based on Phantom JS), how to catch JavaScript errors that are loaded after the DOM is done?

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

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

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

为了 运行 代码,安装 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);

看来您注入脚本 inject.js 太晚了,已经在页面加载和事件触发之后。

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

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


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

it won't show the ReferenceError if the run() function is ran via the DOMContentLoaded event

正如我们现在所知,它实际上从未 运行 通过 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;
  }
}

并发现它不会 运行(并不是说它不会因为严格模式而产生错误)。