使用 CasperJS 中的函数返回 iframe 内的链接

Returning links inside iframe using a function in CasperJS

我正在尝试从 iframe 中获取链接并将它们 return 作为函数结果,我的简化代码如下所示:

var casper = require("casper").create({
    verbose: true,
    logLevel: "debug",
        webSecurityEnabled: false
});

var url = casper.cli.get(0);

casper.on('remote.message', function(msg) {
    this.echo(msg);
})

casper.start(url, function () {
    thelinks = getLinksFromIframes( casper );
    console.log("doesn't work:" + thelinks);
});

function getLinksFromIframes( context ) {
        var links = [];

        var iframes = context.evaluate( function() {
                var iframes = [];
                [].forEach.call(document.querySelectorAll("iframe"), function(iframe, i) { iframes.push( i ); });
                return iframes;
        });

        iframes.forEach( function( index ) {
            context.withFrame(index, function() {
                links = links.concat( this.getElementsAttribute( 'a', 'href' ) );
                console.log("works: " + links);
            });
        });

        return links;
}

casper.run(function() {
    console.log('done');
    this.exit();
});

问题是该函数没有 return 任何东西,我只能读取 withFrame 中的链接 var,我知道还有其他方法可以获取链接,但代码是这种方式是因为它是分析嵌套 iframe 的更复杂事物的一部分,而 iframe 中的 iframe 数量是未知的。有什么方法可以让我等待 withFrame 或允许我 return 链接作为函数结果的方法吗?

这是预期的,因为 casper.withFrame 是一个异步步骤函数。与所有其他以 thenwait 开头的函数一样,它会在 CasperJS 执行队列中安排一个步骤。

当那些预定的步骤被执行时(在当前步骤的末尾,在你的例子中是 casper.startthen 回调),getLinksFromIframes 早已完成并返回空数组。

Is there any way I could wait on withIframe or something that will allow me to return the links as the function result?

否,但您可以使用回调:

function getLinksFromIframes( callback ) {
    var links = [];

    var iframes = this.evaluate( function() {
        var iframes = [];
        [].forEach.call(document.querySelectorAll("iframe"), function(iframe, i) { iframes.push( i ); });
        return iframes;
    });

    iframes.forEach( function( index ) {
        this.withFrame(index, function() {
            links = links.concat( this.getElementsAttribute( 'a', 'href' ) );
            console.log("works: " + links);
        });
    }, this);

    this.then(function(){
        callback.call(this, links);
    });
}

casper.start(url, function () {
    getLinksFromIframes.call(this, function(links){
        thelinks = links;
        console.log("Links: " + thelinks);
    });
})
.then(function(){
    console.log("Links later: " + thelinks);
})
.run();