Javascript 如何从casper.start或casper.open中调用外部函数

Javascript 如何从casper.start或casper.open中调用外部函数,javascript,casperjs,function-call,Javascript,Casperjs,Function Call,我试图拆分以下代码,以使回调函数存储在自己的文件中 var casper = require('casper').create(); casper.start("http://www.google.com/", function() { this.echo(this.getTitle()); }); casper.run(); // "Returns Google" 接下来,我在一个名为“getPageTitle.js”的单独文件中定义了一个函数 通过将CasperJS对象直接传递到函

我试图拆分以下代码,以使回调函数存储在自己的文件中

var casper = require('casper').create();
casper.start("http://www.google.com/", function() {
    this.echo(this.getTitle());
});
casper.run(); // "Returns Google"
接下来,我在一个名为“getPageTitle.js”的单独文件中定义了一个函数

通过将CasperJS对象直接传递到函数中,调用另一个名为“main.js”的文件中的函数

var casper = require('casper').create();
var casperFunctions = require('./getPageTitle.js');
casper.start("http://www.google.com/", casperFunctions.getPageTitle(casper));
# Error: CasperError: Casper is not started, can't execute `getTitle()`                  
此外,如果我将上面的最后一行替换为
thenOpen()
调用

casper.start();
casper.thenOpen("http://www.google.com/", casperFunctions.getPageTitle(casper));
上述代码不会抛出错误;CasperJS可以导航到该网站,但页面标题“Google”不会返回

有人能解释一下为什么这不符合我的预期吗。这似乎是一种模块化函数的自然方式,CasperJS会在页面加载后调用这些函数,但我是否遗漏了一些东西

casper.start("http://www.google.com/", casperFunctions.getPageTitle(casper));
不起作用,因为您正在将调用
casperFunctions.getPageTitle(casper)
的结果作为回调参数传递给casper.start

我认为你应该能够做到这一点

casper.start("http://www.google.com/", casperFunctions.getPageTitle.bind(casper));

CasperJS的执行是异步的
start()
和所有
then*()
wait*()
函数都是异步步进函数。这意味着您只在诸如步骤的内部页面上

当您查看
getPageTitle()
及其调用方式时,应该注意到您并没有将step函数传递到
casper.start()
,而是立即调用
getPageTitle()
。此时,执行甚至还没有开始,因为只要调用
run()
,计划的步骤就开始执行。通过调用
getPageTitle()
,您正试图访问about:blank的标题,该标题为空

第一版:

function getPageTitle(casper) {
    return function(){
        casper.echo(casper.getTitle());
    };
}
现在,您将一个step函数传递到
start()
中,该函数将进行异步计算

第二版:

function getPageTitle(casper) {
    return function(){
        casper.echo(casper.getTitle());
    };
}
请记住,您可以在step函数中使用
来引用
casper
。这是一种更好的方法,因为您不需要显式地传递引用:

function getPageTitle() {
    return function(){
        this.echo(this.getTitle());
    };
}
这样称呼它:

casper.start("http://www.google.com/", casperFunctions.getPageTitle());
casper.start("http://www.google.com/", casperFunctions.getPageTitle);
第三版:

function getPageTitle(casper) {
    return function(){
        casper.echo(casper.getTitle());
    };
}
如果函数不需要任何参数,则不需要包装器函数。您可以直接传递它:

function getPageTitle() {
    this.echo(this.getTitle());
}
这样称呼它:

casper.start("http://www.google.com/", casperFunctions.getPageTitle());
casper.start("http://www.google.com/", casperFunctions.getPageTitle);

可能无法使用PhantomJS 1.x,因为未实现
函数.prototype.bind
。我应该看看
casperjs
是什么,我猜casperjs确实为
函数.prototype.bind
提供了一个垫片,但这是一个非常基本的垫片,可能无法按预期工作。只是为了确认我的理解;我认为在我原来的方法中,
getPageTitle
在casper.start检索url时运行,因此没有返回任何内容,这对吗?第二,添加
函数()
包装器是为了确保
getPageTitle()
只在从
.start()
返回页面后运行?如果这有点基本,我很抱歉,但是同步/异步调用仍然有点混乱。我在你的另一个地方读到你提到生活的地方。函数包装器是否与此等效?否,
start()
仅计划打开URL的步骤。整个执行仅在调用
run()
时开始。此时,您的
getPageTitle()
已经运行并尝试从about:blank访问标题。