什么是“那么”在CasperJS中真正的意思

我正在使用CasperJS通过网站自动化一系列点击,完成表单,parsing数据等。

卡斯珀似乎被组织成一个预设步骤的列表, then语句的forms(参见他们的例子: http : //casperjs.org/quickstart.html ),但不清楚是什么触发了下一个语句实际运行。

例如,是否等待所有待处理的请求完成? injectJS是否injectJS视为未决请求? 如果我有一个嵌套在一个open语句结尾的语句,会发生什么呢?

 casper.thenOpen('http://example.com/list', function(){ casper.page.injectJs('/libs/jquery.js'); casper.evaluate(function(){ var id = jQuery("span:contains('"+itemName+"')").closest("tr").find("input:first").val(); casper.open("http://example.com/show/"+id); //what if 'then' was added here? }); }); casper.then(function(){ //parse the 'show' page }); 

我正在寻找关于CasperJSstream程如何工作的技术解释。 我的具体问题是,我最后的陈述(上面)运行在我的casper.open声明之前,我不知道为什么。

then()基本上在堆栈中添加一个新的导航步骤。 一个步骤是一个JavaScript函数,可以做两件事情:

  1. 等待上一步 – 如果有的话 – 正在执行
  2. 等待请求的url和相关页面加载

我们来看一个简单的导航场景:

 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)'); }); 

您可以像这样打印出堆栈中所有创build的步骤:

 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)'); }" ] 

注意CasperJS自动添加的_step _step()函数为我们加载了url; 当url被加载时,堆栈中的下一步( step3()被调用。

当你定义你的导航步骤时, run()依次执行它们:

 casper.run(); 

脚注:callback/监听器的东西是Promise模式的实现。

then()只是注册一系列的步骤。

run()及其runner函数,callback函数和侦听器系列都是执行每个步骤的实际操作。

每当一个步骤完成,CasperJS将检查3个标志: pendingWaitloadInProgressnavigationRequested 。 如果这些标志中的任何一个是真的,则什么也不做,直到稍后的时间( setInterval样式)。 如果没有这些标志是真的,那么下一步将被执行。

从CasperJS 1.0.0-RC4开始,就存在一个缺陷,在某些基于时间的情况下,在CasperJS有时间提升loadInProgress或者navigationRequested标志之前,会触发“尝试下一步”的方法。 解决的办法是在离开那些标志预期会被提出的任何步骤(例如:在请求casper.click() )之前或之后提出一个标志)之前提升其中的一个标志,也许如此:

(注意:这仅仅是说明性的,更像是正确的CasperJSforms的伪代码)

 step_one = function(){ casper.click(/* something */); do_whatever_you_want() casper.click(/* something else */); // Click something else, why not? more_magic_that_you_like() here_be_dragons() // Raise a flag before exiting this "step" profit() } 

为了将这个解决scheme整合到一行代码中,我在这个github pull请求中引入了blockStep() ,并clickLabel() click()clickLabel()作为一种手段来保证我们在使用then()时获得预期的行为。 查看有关更多信息,使用模式和最低testing文件的请求。