我试图从iframe中获取链接并将其作为函数结果返回,我的简化代码如下所示:

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


问题是该函数不返回任何内容,我只能读取withFrame中的链接var,我知道还有其他获取链接的方法,但是代码是这种方式,因为它是更复杂的部分,分析嵌套的iframe,iframe中iframe的数量未知。有什么方法可以让我等待withFrame还是可以让我返回链接的函数结果?

最佳答案

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

当执行这些计划的步骤时(在当前步骤的末尾,在您的情况下为thencasper.start回调),getLinksFromIframes早已结束并返回了一个空数组。


  有什么我可以等待withIframe的方法,或者可以让我返回链接作为函数结果的方法吗?


不,但是您可以使用回调:

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();

10-07 19:48
查看更多