CasperJS 中的静默错误

Silent errors in CasperJS

我刚开始使用 CasperJs,我很难调试它,因为太多的编码错误似乎会导致脚本在不提供错误消息的情况下退出。当你使用详细模式时,你会得到你应该得到的消息,直到有问题的代码行,然后它就退出了。

例如,如果我执行代码:

var casper = require('casper').create({
    verbose: true,
    logLevel: "debug"
});

casper.start('https://www.google.com/#q=Whosebug', function(){

});
casper.wait(2000, function(){
});


casper.then(function() {
    hrefAr = this.evaluate(getLinks);
    this.log(hrefAr.length + ' links found', 'info');
    this.exit();
});

casper.run(function() {
    this.exit();
});

function getLinks() {
    var links = document.querySelectorAll('a');
    return Array.prototype.map.call(links, function(e) {
        return e.getAttribute('href');
    });
}

我得到以下结果:

...a bunch of info & debug messages, followed by...
[info] [phantom] Step 4/4 https://www.google.com/search?q=Whosebug&cad=h (HTTP 200)
[info] [phantom] 89 links found
[debug] [phantom] Navigation requested: url=about:blank, type=Other, lock=true, isMainFrame=true
[debug] [phantom] url changed to "about:blank"

如果我向函数 getLinks 添加日志语句...

...code as shown above...
function getLinks() {
    this.log('getLinks ran', 'info');
    var links = document.querySelectorAll('a');
...code as shown above...

...这会导致脚本失败,如下所示:

...the same info & debug messages...
[info] [phantom] Step 4/4 https://www.google.com/search?q=Whosebug&cad=h (HTTP 200)
...NO LOGS, ECHOS, OR RESULTS PAST THIS POINT, JUST THESE TWO CLOSING STATEMENTS...
[debug] [phantom] Navigation requested: url=about:blank, type=Other, lock=true, isMainFrame=true
[debug] [phantom] url changed to "about:blank"

它不会告诉你哪里出了问题,它只会让你返回空白并结束执行。

有没有办法获得更好的错误报告?或任何错误报告?


当我尝试使用以下代码实施以下解决方法时:

var casper = require('casper').create({
    verbose: true,
    logLevel: "debug"
});

casper.start('https://www.google.com/#q=Whosebug', function(){

});
casper.wait(2000, function(){
});


casper.then(function() {
    reportErrors(function() {
        hrefAr = this.evaluate(getLinks);
        this.log(hrefAr.length + ' links found', 'info');
        this.exit();
    });
});

casper.run(function() {
    this.exit();
});

function getLinks() {

        //this.log('getLinks ran', 'info');
        var links = document.querySelectorAll('a');
        return Array.prototype.map.call(links, function(e) {
            return e.getAttribute('href');
        });

}

function reportErrors(f) {
  var ret = null;
  try {
    ret = f();
  } catch (e) {
    casper.echo("ERROR: " + e);
    casper.exit();
  }
  return ret;
}

我明白了...

...info & debug messages shown above...
[info] [phantom] Step 4/4 https://www.google.com/search?q=Whosebug&cad=h (HTTP 200)
ERROR: TypeError: undefined is not a constructor (evaluating 'this.evaluate(getLinks)') 
--THIS IS WHERE MY LINK COUNT WOULD BE REPORTED
[debug] [phantom] Navigation requested: url=about:blank, type=Other, lock=true, isMainFrame=true
[debug] [phantom] url changed to "about:blank"

这个有空PhantomJS issue

您可以通过用 reportErrors 函数包装每个 then 和类似的函数来绕过它,例如:

function reportErrors(f) {
  var ret = null;
  try {
    ret = f();
  } catch (e) {
    casper.echo("ERROR: " + e);
    casper.exit();
  }
  return ret;
}

casper.then(function() {
  reportErrors(function() {
    ...
  });
});

在修复 PhantomJS 2.x 中的吞咽错误之前,您可以尝试以下几种方法:

  • 使用 PhantomJS 1.9.8。底层的 QtWebKit 引擎已经有 5 年多的历史了,但它在大多数时候仍然运行良好。如果存在 SSL/TLS 问题,您可以添加命令行选项,例如 --ignore-ssl-errors=true。 CasperJS 支持根据需要为当前终端会话更改 PhantomJS 版本,方法是将 PHANTOMJS_EXECUTABLE 环境变量设置为您要使用的可执行文件或可执行文件的路径。例如,在 Windows 上:set PHANTOMJS_EXECUTABLE=phantomjs198(我在 PATH 中对它们进行了编号)。

  • 如果您担心的是语法错误,那么 运行 首先检查您的代码。我可以推荐eslint和jshint。

  • 使用附加事件检测错误(使用 PhantomJS 1.9.8):resource.errorpage.errorremote.messagecasper.page.onResourceTimeoutExample


关于您的特殊功能。 thisreportErrors的回调中没有意义。您需要绑定另一个对象:

casper.reportErrors = function (f) {
  var ret = null;
  try {
    ret = f.call(this);
  } catch (e) {
    this.echo("ERROR: " + e);
    this.exit();
  }
  return ret;
}

然后你就可以像以前一样使用它了:

casper.then(function() {
    this.reportErrors(function() {
        hrefAr = this.evaluate(getLinks);
        this.log(hrefAr.length + ' links found', 'info');
        this.exit();
    });
});