javascript - 使用 CasperJS 循环等待选择器

标签 javascript phantomjs wait casperjs headless-browser

我想在循环中等待选择器,只要找到的对象不满足指定的条件。我编写了以下代码。

casper.then(
    function(){
        var need_exit = false;
        this.echo('enter loop');
        var i = 1;
        while (!need_exit){
            this.echo('check exit');
            // check, if chat was finished
            if (this.exists('div#chat > p')){
                need_exit = true;
                this.echo('exit loop');
            }
            // wait new message
            else {
                    this.echo('wait msg ' + datetime());
                    var selector = 'div#chat tr:nth-child('+i+')';
                    try{
                        this.waitForSelector(selector,
                            function(){
                                var msg_selector = 'div#chat tr:nth-child('+i+') > td:nth-child(2)';
                                var inf = this.getElementInfo(msg_selector);
                                this.echo(inf['text']);
                                i++;
                            },
                            null,
                        5000);
                    }
                    catch(err){
                        this.echo('[wait timeout]');
                    }
                    need_exit = true;
            }
        }

    }
);

问题在于迭代不断地相互跟随,而不是在找到项目或超时到期后前进到下一次迭代。为什么会发生这种情况以及如何正确执行?

最佳答案

问题是所有 then*wait*调用是异步步骤函数。这就是为什么你不能在它们周围使用循环。解决这个问题的正常方法是使用递归函数:

这是您的函数的重新想象版本:

casper.waitContinuouslyUntilSelector = function(checkRow, finalSelector, then, onTimeout, timeout, i){
    // TODO: remove the `this.echo()` calls from this function
    i = i || 1;
    this.then(function(){
        if (this.exists(finalSelector)) {
            this.echo('finalSelector found');
            this.then(then);
            return;
        }
        this.waitForSelector(checkRow(i), function _then(){
            this.waitContinuouslyUntilSelector(checkRow, finalSelector, then, onTimeout, timeout, i+1);
        }, function _onTimeout(){
            if (this.exists(finalSelector)) {
                this.echo('finalSelector found');
                this.then(then);
            } else {
                this.echo('finalSelector not found');
                if (typeof onTimeout !== "function") {
                    throw new CasperError("Final selector was not found and next row was not loaded");
                }
                this.then(onTimeout);
            }
        }, timeout);
    });
    return this;
}

你可以像这样使用它:

casper.then(function(){
    var bindingExitSelector = 'div#chat > p';
    var rowSelectorFunc = function(i){
        return 'div#chat tr:nth-child('+i+') > td:nth-child(2)';
    };
    this.waitContinuouslyUntilSelector(rowSelectorFunc, bindingExitSelector);
});

如果没有更多行加载并且“最终”<p>也不存在,出现超时错误。如果你想防止这种情况,你需要传入 onTimeout回调:

this.waitContinuouslyUntilSelector(rowSelectorFunc, 
        bindingExitSelector, 
        null, 
        function _onTimeout(){
            this.echo("Failed to load the next row and didn't found the final selector; continue...");
        });

关于javascript - 使用 CasperJS 循环等待选择器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31035965/

相关文章:

java - CryptoJS.SHA1 与 MessageDigest.getInstance ("SHA-1").digest()

javascript - 如何在一个 grunt.registerTask 中调用多个 grunt.run.task?

javascript - 清除ubuntu上的phantomjs缓存

javascript - capybara 无法找到链接 "Delete Comment"

java - 安卓穿戴: very strange wait cycle

java - 如何让 Java 程序暂停,直到按下特定按钮?

javascript - 如何在 AngularJS 中用 $http 替换 $resource ?

javascript - 读取asp.net web api

node.js - 如何在 AWS Lambda 上部署 phantomjs Node 应用程序?

.net - 监视器应该等待什么对象?