1

In the code below I want to call checkMainBox(cthis). I want to set it up so that this function will either return the number retrieved or false. But in checkMainBox() I don't know how to return a value. number is returned undefined. I'm pretty sure I can't to do it this way because of asynchronous behavior but what is the next best way?

function checkMainBox(cthis){
    var number;
    cthis.waitForSelector("._XWk", function(){
        cthis.capture("result.png");
        cthis.then(function(){
            var number = cthis.evaluate(function(){
                return $("._XWk").txt();
            })

            // console.log("number", number);
        })
    })
    return number
}

function getPhoneNumber(cthis){
    console.log("NUMBER::", checkMainBox(cthis));
       //checkMainBox(cthis) should return false or the number
}

casper.on("error", function(msg){
    this.echo("error: " + msg, "Error");
})
casper.on("page.error", function(msg, trace){
    this.echo("Page Error: " + msg, "error");
});
casper.on("remote.message", function(message){
    this.echo("Remote: " + message);
});

casper.start("http://google.com/", function(){
    this.waitForSelector("form[action='/search']");
});
casper.then(function(){
    this.fill("form[action='/search']", {q : "ebay.com phone number"}, true);
})
casper.then(function(){
    getPhoneNumber(this)
})
casper.run();

EDIT::

recent attempt with promise but if you have another way to do it feel free to share it:

function checkMainBox(cthis){
    var number;
    return new Promise(function(resolve, reject){
        cthis.waitForSelector("._XWk", function(){
            cthis.capture("result.png");
            cthis.then(function(){
                var number = cthis.evaluate(function(){
                    return $("._XWk").txt();
                })

                resolve(number)
            })
        });
    })

}

function getPhoneNumber(cthis){
    checkMainBox(cthis).then(function(result){
        console.log("NUMBER::", checkMainBox(result));
    })
    .catch(function(err){
        if(err) console.log(err);
    })

}

ERROR : error: ReferenceError: Can't find variable: Promise

EDIT 2 :

function getPhoneNumber(cthis){
    // var number;
    cthis.waitForSelector("._XWk", function(){
        cthis.capture("result.png");
        cthis.then(function(){
            var number = cthis.evaluate(function(){
                return $("._XWk").html();
            })
            checkMainBox(number);
            // console.log("number", number);
        })
    })
}

function checkMainBox (number){
    // console.log("NUMBER::", number);
    return number
}

...

casper.then(function(){
    this.fill("form[action='/search']", {q : "ebay.com phone number"}, true);
})
casper.then(function(){
    var number;
    console.log(getPhoneNumber(this)) // should be the value

})
casper.run();
jack blank
  • 5,073
  • 7
  • 41
  • 73
  • 2
    Possible duplicate of [How do I return the response from an asynchronous call?](http://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – 4castle Dec 05 '16 at 04:22
  • It looks like you should make `checkMainBox` return a [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) – 4castle Dec 05 '16 at 04:32
  • I still need help restructuring it for this case after reading the top answer.I would like to continue the casper.then() chain in the main part of the code. – jack blank Dec 05 '16 at 04:33
  • can you please show me how? I know about promise. I should make the whole `cthis.waitForSelector` into a promise and then return it? – jack blank Dec 05 '16 at 04:37
  • I tried it : `error: ReferenceError: Can't find variable: Promise` – jack blank Dec 05 '16 at 04:45
  • 1
    If promises aren't available, you can give `checkMainBox` a callback function as a parameter, and call it when the value is available. The dupe question shows how to do that. – 4castle Dec 05 '16 at 04:49
  • I did something like what you suggested but I would still like the `number` value in the main `casper.then()` thread. is it possible? see second edit. – jack blank Dec 05 '16 at 05:30
  • @jackblank `casper.wait(4000).then(function(){getPhoneNumber(this) })` because `casper.then(function(){` will be executed instantly, after submitting a form. –  Dec 05 '16 at 06:38
  • @jackblank as it going? –  Dec 06 '16 at 06:14
  • If the given answer solved your problem, you may [accept](http://meta.stackexchange.com/q/5234/266187) it. If it didn't, then please expand on what is wrong. – Artjom B. Apr 08 '17 at 11:07

1 Answers1

1

You could just use a poor man's Promise (important stuff is bold):

function checkMainBox(cthis){
    var number = {};
    cthis.waitForSelector("._XWk", function(){
        cthis.capture("result.png");
        cthis.then(function(){
            number.value = cthis.evaluate(function(){
                return $("._XWk").txt();
            })
        })
    })
    return number
}

function getPhoneNumber(cthis){
    var number = checkMainBox(cthis));
    cthis.then(function(){
        console.log("outer: " + number.value);
    });
}

CasperJS already provides an environment that is similar to Promises, but you still have to have an empty object that can receive the value asynchronously. The cthis.then is important because it handles the waiting until the cthis.waitForSelector inside of checkMainBox is finished.

Artjom B.
  • 61,146
  • 24
  • 125
  • 222