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

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.

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

Sammyjs routes not working with Phonegap

I have built an app with SammyJs. It currently works perfectly in the browser. However, when I package it to Android using PhoneGap, the routes does not work anymore.
I have found this SO question. However, the solution given does not work :
(function($) {
var app = $.sammy('[role=main]', function() {
this.disable_push_state = true;
...
});
}
Has anyone ever experienced the same issue?
EDIT
I am also using jquery mobile with the following script to disable its routing :
<script type="text/javascript">
// DISABLE JQM ROUTER
$(document).bind("mobileinit", function () {
$.mobile.ajaxEnabled = false;
$.mobile.linkBindingEnabled = false;
$.mobile.hashListeningEnabled = false;
$.mobile.pushStateEnabled = false;
$.mobile.changePage.defaults.changeHash = false;
});
</script>
I created a gist with my app sammy javascript (including routes).
I think the problem is with this around clause:
this.around(function(callback) {
var context = this;
url = 'http://localhost:3000/api.json?school=' + localStorage.school
this.load(url)
.then(function(data) {
parsed = JSON.parse(data);
//if (parsed.meta != undefined) {
// alert(parsed.meta.message);
//}
context.products = parsed.products;
context.places = parsed.places;
context.school = parsed.school;
context.title = $('[data-role=header] h1');
})
.then(callback); // *** this won't get called if load() rejects promise
});
As I understand it, the around clause is called with a callback(), which will continue loading the route when it is called.
I think there is a problem with your promise chain. If load() returns a rejected promise (which probably does, as there is no localhost:3000 on your phone), then neither of your then() functions will load. As such, callback() isn't called and the app "stops". I would advise (a) adding some error handling there, so you can see what it happening, and definitely (b) executing callback no matter the result of load(). Also - JSON.parse(data) will throw an error if data is not a proper JSON-encoded string - you want a try/catch around that, too.
I would try this:
this.load(url)
.then(function(data) {
try {
parsed = JSON.parse(data);
} catch(e) {
console.log('error decoding json!: '+errorMsg);
}
//if (parsed.meta != undefined) {
// alert(parsed.meta.message);
//}
context.products = parsed.products;
context.places = parsed.places;
context.school = parsed.school;
context.title = $('[data-role=header] h1');
},function(errorMsg){
console.log('error loading json!: '+errorMsg);
})
.fin(callback); // *** fin() is meant to execute on both success and error, like a "finally".
If your promises implementation does not support fin(), look up what it is calling its equivalent. It is essentially shorthand for: .then(callback).otherwise(callback)
Long story short - you want to make sure that the callback passed to around will be executed no matter what, or you app will not continue loading the route, which is what your unexpected behaviour seems to be.
As for the point about not being able to see the console, I am not sure what your environment looks like, but I have had success with Eclipse and ADT in the past - I can see console logs and errors just fine.

Uncaught SyntaxError: Unexpected token %

I have a page with multiple YouTube embedded players that I need to listen for events on. I am trying to use the solution posted as the answer to Using Youtube's javascript API with jQuery, but I am getting a strange error: (in Chrome 18.0.1025.137 beta-m)
Uncaught SyntaxError: Unexpected token %
That is the extent of the error, including stacktrace. My code is like this:
var onYouTubePlayerReady = function (id) {
var evt = '(function(){})';
alert(eval(evt)); //just to verify that the snippet is syntactically correct
var ytplayer = document.getElementById(id);
ytplayer.addEventListener("onStateChange", evt);
};
(see the other question for more context)
The error is thrown when the onStateChange event is fired. If I make evt "" or a function name, then it doesn't throw the error (but I also get no state information).
Clearly, the error message is bogus, but anyone know if what I'm trying to do is possible?
Actually, turns out it's incredibly stupid. Running the code in Firefox yielded a real error message:
syntax error
try { __flash__toXML(%28function%28%29%7B%7D%29(5)) ; } catch (e) { "<undefined/...
---------------------^
So, apparently, it needs to be serializable to XML in order to be used as a callback. Which is really kind of annoying.
My solution was something like this:
var ytCallbackID = 1;
var makeYTCallback = function (func) {
var ret = "ytCallback" + (ytCallbackID++);
window[ret] = func;
return ret;
}
var onYouTubePlayerReady = function (id) {
var evt = makeYTCallback(function(state) {
onYouTubePlayerStateChange(id, state);
});
var ytplayer = document.getElementById(id);
ytplayer.addEventListener("onStateChange", evt);
};
I haven't fully tested it (since I did this right at the end of the day yesterday), but I think it'll work.
Got around to testing it, and it works like a charm! It's a bit fugly, both in idea and implementation, but it works and that's what's important :)

Prototype.js error on a function

I am getting error on following function:
Event.observe(window, "load", function () {
if ($("question") && $("question").type.toLowerCase() == "textarea") {
Event.observe("question", "keyup", function () {
var _4 = $F("question");
if (_4.length > 255) {
$("question").value = _4.substring(0, 255);
}
});
}
});
type is null or not an object.
in prototype.js it gives error on:
var respondersForEvent = registry.get(eventName);
if (Object.isUndefined(respondersForEvent)) {
respondersForEvent = [];
registry.set(eventName, respondersForEvent);
}
Try wrapping it in a $(document).ready(). I believe the window load event will fire before all the DOM nodes are created.
As an aside, I have to support a legacy app that uses both jQuery and Prototype. If my javascript throws nearly any error, Firebug and Chrome will report it as an error in Prototype.js. Since I've almost completely undone Prototype, it's never the real problem.
In the circumstances, I assume that it's NEVER prototype and start debugging my own code that's fired by this page.

log errors with stack trace in 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.

Categories

Resources