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.
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