【问题标题】:How can I reuse a variable populated within a casperJS call in a subsequent call?如何在后续调用中重用 casperJS 调用中填充的变量?
【发布时间】:2015-11-07 04:52:42
【问题描述】:

我在 CasperJS 脚本中有以下范围问题。传入 casper.thenOpenAndEvaluate() 时,baseTargetUrl 未定义。为什么会这样,我该如何解决?

var baseTargetUrl;
        .....
casper.then(function() {
    baseTargetUrl = this.evaluate(function() {
        return __utils__.getElementByXPath('//*[@id="wrapper"]/div[1]/a[2]')["href"];
    });
    console.log('logging: '+baseTargetUrl); // works
});

casper.thenOpenAndEvaluate(baseTargetUrl ,function() { //baseTargetUrl is undefined here
    var test = document.querySelector('myselector');
    //do other stuff

});

【问题讨论】:

    标签: javascript casperjs


    【解决方案1】:

    如您所知,我们无法从外部异步调用中获取变量。这看起来有点老套,但这是我目前最好的....

    var baseTargetUrl;
            .....
    casper.then(function() {
        baseTargetUrl = this.evaluate(function() {
            return __utils__.getElementByXPath('//*[@id="wrapper"]/div[1]/a[2]')["href"];
        });
        console.log('logging: '+baseTargetUrl); // works
    
        this.thenOpenAndEvaluate(baseTargetUrl ,function() { // 'this' being the instance of casper
            var test = document.querySelector('myselector');
            //do other stuff
    
        });
    });
    

    【讨论】:

    • 谢谢!为什么不能从“外部”获取变量?是因为你还不能保证它们会存在吗?
    • 当您运行casper.run() 时,casper 套件开始执行。此时您已经使用undefined 调用/安排了thenOpenAndEvaluate。嵌套似乎是最好的方式,因为 casperjs 处理得很好。
    【解决方案2】:

    处理此问题的常用方法(有充分理由)是使用 Promise。

    promise 有许多不同的实现。许多框架都有自己的 Promise,例如 jQuery 和 AngularJS。还有独立的 Promise 框架,例如 Q

    Promises 是一种通过解析值来链接方法的方式。解决后,将调用链中的下一个函数。

    当您使用 Q 时,您的代码可能如下所示:

    var baseTargetUrl = Q.defer();
            .....
    casper.then(function() {
        var value;
        baseTargetUrl.resolve(value = this.evaluate(function() {
            return __utils__.getElementByXPath('//*[@id="wrapper"]/div[1]/a[2]')["href"];
        }));
        console.log('logging: ' + value); // works
    });
    
    baseTargetUrl.then(function (value) {
        casper.thenOpenAndEvaluate(value, function () { // value contains the result of the call above
            var test = document.querySelector('myselector');
            //do other stuff
        });
    });
    

    Promise 是一种处理异步代码的方式,以防止它变成意大利面条,以保持事情正常。

    在这样的小情况下,简单地嵌套函数也可能是您的解决方案。

    var baseTargetUrl;
            .....
    casper.then(function() {
        baseTargetUrl = this.evaluate(function() {
            return __utils__.getElementByXPath('//*[@id="wrapper"]/div[1]/a[2]')["href"];
        });
        console.log('logging: '+baseTargetUrl); // works
    
        casper.thenOpenAndEvaluate(baseTargetUrl ,function() { //baseTargetUrl is no longer undefined, it's a closure now
            var test = document.querySelector('myselector');
            //do other stuff
    
        });
    });
    

    【讨论】:

    • 嘿,我喜欢你的承诺解决方案。不过小问题,似乎我们无法加载 q 模块并将其作为 casperjs 脚本运行。运行它的唯一方法似乎是通过phantomjs-node。有什么想法吗?
    • 谢谢!你能解释一下“问题”是什么吗?是不是在我尝试使用时未填充 baseTargetUrl 变量?
    • @dcodesmith 对不起,我不太了解 CasparJS 是如何运行的,但我无法想象没有办法在环境中加载外部 JS,因为那是相当的限制。 Node确实可以解决这个问题。
    • @codecowboy,问题在于 caspen.then 是一个异步函数,您无法从所述函数外部访问函数内部设置的变量
    • @codecowboy 这正是问题所在。 then 函数接受一个回调,它会在它下面的代码之后调用它。最有可能的是,如果您使用 1 秒之类的超时,它将不再是未定义的,但这将是一个竞争条件,可能会导致各种麻烦。 Promise 解决了这个问题。
    【解决方案3】:

    waitFor怎么样?

    var baseTargetUrl;
    
    casper.then(function() {
        baseTargetUrl = this.evaluate(/**/);
    });
    
    casper.waitFor(function() {
        return typeof baseTargetUrl !== "undefined";
    }, function() { 
        var test = document.querySelector('myselector');
        // ...
    });
    

    【讨论】:

    【解决方案4】:

    这对我很有效:

    var dre_num = "12345678";  // global
    casper.getdre = function() {
        return dre_num;
    }
    casper.setdre = function(str) {
        dre_num = str;
    }
    
    casper.then(function(){
        this.setdre("01833946");
    });
    casper.then(function(){
        this.echo("dre_num : " + this.getdre());
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-28
      • 2020-06-20
      • 2017-01-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多