Reputation: 25443
I'm having a hard time understanding how PhantomJS handles errors.
I have a locally installed Apache server running (xampp), and when I manually visit "http://localhost/" I get the "It Works!" page.
As a test, I wrote a small file (called forceError.js) that purposely causes an unchecked exception:
var page = require('webpage').create(),
url = 'http://localhost/';
page.onError = function(msg, trace) {
console.log("page.onError");
var msgStack = ['ERROR: ' + msg];
if (trace && trace.length) {
msgStack.push('TRACE:');
trace.forEach(function(t) {
msgStack.push(' -> ' + t.file + ': ' + t.line + (t.function ? ' (in function "' + t.function +'")' : ''));
});
}
console.error(msgStack.join('\n'));
};
phantom.onError = function(msg, trace) {
console.log("phantom.onError");
var msgStack = ['PHANTOM ERROR: ' + msg];
if (trace && trace.length) {
msgStack.push('TRACE:');
trace.forEach(function(t) {
msgStack.push(' -> ' + (t.file || t.sourceURL) + ': ' + t.line + (t.function ? ' (in function ' + t.function +')' : ''));
});
}
console.error(msgStack.join('\n'));
phantom.exit(1);
};
page.open(url, function (status) {
console.log("status: " + status);
// an undefined function
thisShouldForceAnError();
});
When I run this using:
phantomjs.exe forceError.js
First I get "status: success" and then the process just hangs. I don't see either page.onError or phantom.onError being invoked.
Is there some property or something I need to turn on to get general error handling?
I'm on Windows 7, PhantomJS version 2.0.0, and running this in my "git bash" shell.
Upvotes: 12
Views: 13753
Reputation: 321
Your app hangs because it looks there is a loop when you call console.error
within phantom.onError
. Check this: Phantomjs v2, consume huge memory+cpu, after throwing exception.
Upvotes: 1
Reputation: 1208
The accepted answer was very helpful, but I'll supplement it with a code sample.
page.open("https://www.google.com/", function (status) {
try {
if (status !== "success") {
console.log("Unable to access network");
} else {
//do some stuff with the DOM
}
} catch (ex) {
var fullMessage = "\nJAVASCRIPT EXCEPTION";
fullMessage += "\nMESSAGE: " + ex.toString();
for (var p in ex) {
fullMessage += "\n" + p.toUpperCase() + ": " + ex[p];
}
console.log(fullMessage);
}
});
Output will look similar to this screen snip:
UPDATE:
This appears to be a bug specifically with page.open
. I noticed that phantom.onError
was catching things from callbacks, just not directly inside page.open
. Here is another possible workaround. This at least allows you to have all the error handling code in one spot instead of having a bunch of try/catches. NOTE: You still need page.onError
for things inside page.evaluate
.
page.open(genericSignInPageUrl, function (status) {
setTimeout(function () { //hack for page.open not hooking into phantom.onError
if (status !== "success") {
throw new Error("Unable to access network");
}
//do some stuff
}, 0);
});
When actually doing things with the page, I've started using this to make sure the element I am looking for is there. Since my code is in a callback, the onError
methods work fine. Code for the waitFor
method is here:
https://github.com/ariya/phantomjs/blob/master/examples/waitfor.js
page.open(genericSignInPageUrl, function () {
waitFor(function () {
return page.evaluate(function () {
return document.getElementById("idOfElementToIndicatePageLoaded");
});
}, function () {
//do some stuff with the page
});
});
Upvotes: 6
Reputation: 20348
Tested on MacOS and experienced exactly the same behaviour, which indeed is a bit unintuitive and most likely just a bug. The weird thing is that, if you call an undefined function from the top most scope phantom.onError
is invoked correctly1.
As a workaround you can just wrap body of the open
callback with a try/catch
. Hopefully it will do the job.
Just to clarify: page.onError
is invoked if an error occurred while executing code of the requested page - not the phantom script itself.
I have been relying on page.onError
for a while now and it seems to work pretty stable. (Although some errors only occur in phantomjs engine, but not in regular browsers.)
1 Actually: "phantom.onError"
gets printed on the console infinitely as console.error
is not supported by phantomjs.
Upvotes: 7