如何在CasperJS中异步单击时停止循环

时间:2015-09-06 12:06:37

标签: javascript if-statement for-loop xpath casperjs

我使用CasperJS抓取多个页面,但我遇到了问题。

最大页数为200,但如果下面的XPath不存在(对于200日之前的页面),我想停止执行。

如何设置i变量?

var casper = require('casper').create();
var x = require('casper').selectXPath;

for (var i=1; i <=200; i++) {
    casper.wait(6000, function() {

        casper.thenClick(x('//*[@id="mArticle"]/div[2]/a['+i+']'), function (){
            console.log('Searching dic');
            words = words.concat(this.evaluate(getWords));
        });

    });
}

1 个答案:

答案 0 :(得分:2)

CasperJS提供exists()功能。因此,您可以像这样重写代码:

for (var i=1; i <=200; i++) {
    (function(i){
        casper.wait(6000, function() {
            var button = x('//*[@id="mArticle"]/div[2]/a['+i+']');
            if (!this.exists(button)) {
                this.echo(i + " not available");
                return; // the following `thenClick()` is not executed
            }
            this.thenClick(button, function (){
                console.log('Searching dic');
                words = words.concat(this.evaluate(getWords));
            });
        });
    })(i);
}

我还添加了一个IIFE,以便在回调中包含正确的i。有关详细信息,请参阅JavaScript closure inside loops – simple practical example

这是有效的,但是如果假设如果链路100不存在则不是非常有效,那么链路101和102等也不存在。你会等很多(6秒乘100)。在这种情况下,由于CasperJS的异步特性,你需要递归地执行此操作:

function execOnce(casper, i, max){
    // end condition
    if (i === max) {
        return;
    }
    casper.wait(6000, function() {
        var button = x('//*[@id="mArticle"]/div[2]/a['+i+']');
        if (!this.exists(button)) {
            this.echo(i + " not available");
            return;
        }
        this.thenClick(button, function (){
            console.log('Searching dic');
            words = words.concat(this.evaluate(getWords));

            // recursive step
            execOnce(this, i+1, max);
        });
    });
};

casper.start(url);

// start the recursive chain
casper.then(function(){
    execOnce(this, 1, 200);
});

casper.run();

请注意,现在您已经递归地使用它,您可以通过在页面上明确查看其中的内容以及不是什么来定义正确的结束条件。