log errors with stack trace in javascript - javascript

I'm trying to log javascript errors on a productive site. So far it worked quite well with the following code included in the site:
function catcherr(errorMessage, url, line) {
var parameters = "msg=" + escape(errorMessage)
+ "&url=" + escape(url)
+ "&line=" + escape(line);
new Image().src = "/error.gif?" + parameters;
return false;
};
window.onerror = catcherr;
I'm trying to add a stack trace to the errors to get more information. This basically works with the following idea including into the function above:
try { i.dont.exist += 0; } // does not exist - that's the point
catch (e)
{
if (e.stack) // Firefox
{
// do some stuff
I use jquery, a simple example:
<script type="text/javascript">
jQuery(document).ready(function() {
p.foo += 1; // this should throw an error
// do stuff
});
</script>
The funny part is, that when I have an error inside the "ready" function of jquery, the part "try { i.dont.exist += 0; }" does not throw any exception anymore and the engine stops without any error.
With the example above, and catcherr extended as follows, only "1" gets alerted:
function catcherr(errorMessage, url, line) {
try { alert(1); i.dont.exist += 0; alert(4);} catch(e) { alert(5);}
alert(2);
var parameters = "msg=" + escape(errorMessage)
// ...
}
Anyone having an idea why this breaks, when an error occurs inside the "ready" function of jquery?

I don't know why you have that problem (it looks very weird and I don't think its a problem with JQuery eating your exceptions, as your alert(1) wouldn't have fired), but I did want to mention your use of Error.stack - when the onerror event gets called, you do not have the stack context of the original error, so getting a stack trace at that point (by catching your own error) will not yield a meaningful stack.
But back to a real answer - instead of simulating a problem by writing specifically broken code so you can catch the error, how about just directly throwing an error? The first line in your onerror handler could be:
try { throw new Error("dummy"); } catch (e) { alert(e.stack); }
This is valid code which will more likely not cause you problems.

Most likely jQuery is wrapping the callback in its own try/catch and ignoring the error.

Try a different exception inside the try/catch.
like a=1/0 or baddarr[5]='bad' and see if those trigger exceptions.
Sometimes "Object Not Found" errors may be as a result of objects not being loaded yet, and there might be different handling for those than other exceptions.

Related

Should setting window.location.href cause the "old" page to stop running JavaScript?

I'm seeing unexpected behavior when setting window.location.href. My understanding is that the current page will be navigated away from immediately -- effectively ignoring subsequent JavaScript in the containing script. However, this is not what I'm seeing in practice (Firefox, Chrome and mobile Safari). I'm setting window.location.href when I encounter an error condition (e.g. missing some data) and yet the script continues to run and spew a bunch of errors because of said error condition. (This also applies to window.location.assign.)
Example:
function handleError() {
window.location.href = "https://example.com"
}
function doWork(id) {
if (!id) {
handleError();
}
var oops = id.split("-");
// a bunch of errors spill into the console, onerror listeners, etc.
}
Why not simply add a return after the guard clause?
function handleError() {
window.location.href = "https://example.com"
}
function doWork(id) {
if (!id) {
handleError();
return
}
var oops = id.split("-");
// a bunch of errors spill into the console, onerror listeners, etc.
}

Why does try..catch not work with chrome.windows.get?

I am trying to open a window by Chrome extension by browser action.
var wid = null;
chrome.windows.get(wid, function(chromeWin) {
chrome.windows.create({'url': 'https://google.com'}, function(chromeWin) {
wid = chromeWin.id;
}
);
});
To prevent multiple copies of the Window, I am trying to check window id. But if used first time, understandably, it throws error because wid is null.
Error: Invocation of form windows.get(null, function) doesn't match definition windows.get(integer windowId, optional object getInfo, function callback)
I tried to use try..catch block and in catch I am handling "wid is null" case.
try {
var wid = null;
chrome.windows.get(wid, function(chromeWin) {
chrome.windows.create({'url': 'https://google.com'}, function(chromeWin) {
wid = chromeWin.id;
}
);
});
}
catch(error) {
chrome.windows.create({'url': 'https://google.com'}, function(chromeWin) {
wid = chromeWin.id;
}
);
}
But try..catch is not catching the "wid is null" case. I know if clause may help for my experiment but I want to learn why try behaves this way.
Why is try..catch not caching the error and how can I open windows without copies in Chrome?
The answer is actually going to be rather boring: it does work for call-validation performed by Chrome API, since that happens synchronously:
try {
var wid = null;
chrome.windows.get(wid, function(chromeWin) {
console.log("This should never be visible.");
});
} catch(e) {
console.log("Error caught!");
console.warn(e);
}
This catches the error (and shows it as a warning instead). So your original problem must be elsewhere (another part of code, not reloading the code properly, something like that).
My original point was that some errors happen inside Chrome's async processing. This is not this error, but rather errors reported with chrome.runtime.lastError. If you do not check that value, and there is an error, it raises an exception that cannot be caught, because it happens after the original invocation and outside your callback.
More information about that here, but again, that does not apply in your case.

Javascript seems to get out of the control flow

I have a problem and I don't know how to fix it ... in the following code - the control seems to never reach the changePage command! I guess that's a problem of the control flow in the addToGlobal function ... is this possible?
$(document).ready(function() {
var globalData = {};
function addToGlobal(name, value) {
globalData[name] = value;
};
$('#tempform').submit(function (event) {
event.preventDefault();
console.log("preventDefault Temp")
var form = $(this);
// add to globalData
addToGlobal("TemperatureU", form.data('clicked'));
$.mobile.changePage('#page2', {transition: 'slide'});
});
});
You have a small syntax error. You are missing a closing ) at the end of the ready handler.
The first step for any JS problem should be to check the console for any error messages. I ran your code, and saw the syntax error in the console showing a missing parenthesis.
The only reason that addToGlobal wouldn't run is if form.data('clicked') is throwing an error. I suggest adding a few more console.logs around to see what's really going on.
console.log(form.data('clicked'));
addToGlobal("TemperatureU", form.data('clicked'));
console.log(globalData);

Dynamically changing the size of a <div> element

I'm trying to resize a <div> when the function is called from this if statement. I know the if statement is working because when the function mTr() is called it works and I know the function myFun() works but for some reason the function myFun() isnt getting called.
if (window.screen.height==568) { // iPhone 4"
document.querySelector("meta[name=viewport]").content="width=320.1";
myFun("divId");
mTr();
}
function myFun(id)
{
var obj = document.getElementById(id);
if (obj)
{
obj.setAttribute("style", "height:300px;");
}
}
function mTr()
{
alert("Hello World!");
}
There are several reasons that myFun() wouldn't be getting called:
window.screen.height is not exactly 568
document.querySelector("meta[name=viewport]").content="width=320.1"; generates a script error that causes script execution to stop
There is some error before this code that causes execution to stop
Your code is executing too early before the DOM has been loaded and thus it can't find the relevant DOM elements.
The first thing to do is to examine your browser error console and see what script errors (if any) are reported.
The second thing to do it to set a breakpoint on the if statement in your javascript debugger (built into most browsers) and then step through each of the following statements to see what is happening.
You can also embed console.log("xxx") statements in your code to create a breadcrumb trail in the console to tell you what's going on.
I retested everything. I think I found your problem. You had an error in your code.
Error was here:
document.querySelector("meta[name=viewport]").content="width=320.1";
Instead, it should be:
document.querySelector("meta[name=viewport]").setAttribute('content', 'width=320.1');
Complete Javascript:
if (window.screen.height==568) {
document.querySelector("meta[name=viewport]").setAttribute('content', 'width=320.1');
myFun("divId");
mTr();
}
function myFun(id)
{
var obj = document.getElementById(id);
if (obj)
{
obj.setAttribute("style", "height:300px;");
}
}
function mTr()
{
alert("Hello World!");
}
You can test it out here:
http://jsfiddle.net/KwGwd/

Checking if image properly loaded with Qunit

I'm trying to validate image URLs with Qunit by setting the URL as the src attribute of a test image and checking with the error event handler whether that went well. So far what I have is:
test('image',function() {
var test_image = $('#test-image');
test_image.error(function(e) { // properly triggered
console.log(e);
is_valid = false;
// ok(false,'Issue loading image'); breaks qunit
});
var is_valid = true;
test_image.attr('src','doesntexist');
console.log('checking is_valid'); // occurs before error event handler
if (is_valid) { // therefore always evaluates to the same
ok(true,'Image properly loaded');
} else {
ok(false,'Issue loading image');
}
});
My problem is that although the error event is properly triggered, it seems to occur in an asynchronous fashion and after the evaluation of is_valid (therefore whatever check I make, the result will always be the same). I have tried adding the ok() assertion inside the error event handler, but I'm getting the following error:
Error: ok() assertion outside test context
How can I run an assertion based on the processing performed inside the error event handler?
PS: if I insert a alert('test'); before checking is_valid it works fine (which confirms problem with error handler being asynchronous) but as you can imagine is not acceptable. I tried using setTimeout to delay execution of if statement but it brings the same assertion context error.
By quickly looking through QUnit API, I see that you should use asyncTest function for this. Before setting the src-attribute for your test_image, hook a function to load event. Here's an untested code:
asyncTest('image',function() {
var test_image = $('#test-image');
test_image.error(function(e) {
console.log(e);
ok(false,'Issue loading image');
start();
});
test_image.load(function() {
ok(true,'Image properly loaded');
start();
});
test_image.attr('src','doesntexist');
});

Categories

Resources