Phantomjs和Javascript一样,是基于消息驱动的。代码的执行都是异步化的。
要理解phantomjs的代码执行是基于一个step栈。在执行脚本时,会将所有step压入栈。
wait,then,open,等这些都是一个step。
举几个例子:
casper.wait(1000,function() {
do1
}
do2
do1和do2执行顺序是怎么样的?
wait方法是异步的!!!,do2会先执行!!!,为了让do1和do2顺序执行,必须这样:
casper.wait(1000,function() {
do1
}
casper.then(function() {
do2
}
wait方法先被压入step栈,然后then被压入栈。
then() 方法将一个新的step压入栈,一个step是一个javascript的函数:
1. 等待前一个step完成后执行
2. 等待页面请求的url或其他page加载
来看一段代码:
var casper = require('casper').create();
casper.start();
casper.then(function step1() {
this.echo('this is step one');
});
casper.then(function step2() {
this.echo('this is step two');
});
casper.thenOpen('http://google.com/', function step3() {
this.echo('this is step 3 (google.com is loaded)');
});
casper.run();
可以将steps栈打印出来方便调试:
require('utils').dump(casper.steps.map(function(step) {
return step.toString();
}));
可以看到栈信息是这样的:
$ casperjs test-steps.js
[ "function step1() { this.echo('this is step one'); }", "function step2() { this.echo('this is step two'); }", "function _step() { this.open(location, settings); }", "function step3() { this.echo('this is step 3 (google.com is loaded)'); }" ]
栈信息里,有一个_step(),这个是phantomjs自动帮我们加的,用于加载google.com这个url,然后step3才能执行。
栈里的step,必须在调用run后才真正开始执行。
如果一个step内部有多个step,会怎么样?代码大概是这样:
casper.then(function() {
casper.then(function() {
do1
casper.then(function() {
do2
})
do3
})
do4
)
casper.then(function() {
do5
})
一个step内部递归的step,在运行时,会动态压入所在step的内部栈。所以,执行顺序是:do4,do1,do3,do2,do4
在sendAjax的时候,将asyn参数设为false,就可以正常执行,得到返回值result,否则是空
var result = this.evaluate(function () {
return __utils__.sendAJAX(url, 'GET', null, false,
{
contentType: 'application/x-www-form-urlencoded; charset=UTF-8'
});
}, {url: url});
exit()方法是异步的,也就是说,step1中调用exit,step2也有可能执行。