Is there a way to listen to an event in the phanto

2019-03-16 08:07发布

问题:

For example: I open a page with PhantomJS, evaluate an asynchronous script (e.g. ajax). When it succeeds, I want to let the phantom context (outside of page.evaluate()) know that the asynchronous process is finished.

I don't want to use setTimeout and setInteval to wait and check continously in the phantom context that the process is finished.

回答1:

That is exactly what the onCallback and window.callPhantom() pair is for.

So, if you have an asynchronous call in the page context like an AJAX request, you can do this:

page.onCallback = function(data){
    console.log("finished: " + data.text);
    phantom.exit();
};
page.evaluate(function(){
    var xhr = new XMLHttpRequest();
    xhr.open("GET", "/");
    xhr.onreadystatechange = function () {
        var DONE = this.DONE || 4;
        if (this.readyState === DONE){
            window.callPhantom({text: this.responseText});
        }
    };
    xhr.send();
});

The other way to use this is to add the call to your production JavaScript to make testing easier. If you're writing a web application it is sometimes complicated to find a selector which denotes when a page is fully loaded. To make testing such an application easier, you can have something like this in the page JavaScript:

finishOffPage(function callback(){
    if (typeof window.callPhantom === "function") {
        window.callPhantom({type: "loadFinished"});
    }
});

Then you can write tests like this:

page.onCallback = function(data){
    if (data.type === "loadFinished") {
        // do some testing
    }
};
page.open(url);

This is an example where such a thing can be added dynamically: wait for angular app to be fully rendered from phantom script