How can I reuse a variable populated within a casperJS call in a subsequent call?

梦想的初衷 提交于 2019-12-11 02:34:49

问题


I have the following scoping problem in a CasperJS script. baseTargetUrl is undefined when passing into casper.thenOpenAndEvaluate(). Why is this and how can I work around it?

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

});

回答1:


As you know we can't grab variable from outside async calls. This seem kinda hacky but this is the best I've got for now ....

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

    });
});



回答2:


A commonly used method (for good reasons) for dealing with this problem is using a promise.

There are many different implementations of promises. A lot of frameworks have their own promises included, such as jQuery and AngularJS. There are also stand alone promise frameworks, such as Q.

Promises are a way of chaining methods by resolving values. Once resolved the next function in the chain will be called.

When you'd use Q, your code could look like:

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

Promises are a way of dealing with async code to prevent it from becoming spaghetti, to keep things sane.

In a small situation like this, simply nesting the functions could be your solution too.

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

    });
});



回答3:


How about using waitFor?

var baseTargetUrl;

casper.then(function() {
    baseTargetUrl = this.evaluate(/**/);
});

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



回答4:


This simply worked for me:

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


来源:https://stackoverflow.com/questions/20932947/how-can-i-reuse-a-variable-populated-within-a-casperjs-call-in-a-subsequent-call

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!